You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何基于PHPUnit数据提供者参数彻底忽略测试用例?

解决PHPUnit中跳过测试不显示在结果中的问题

问题场景

我使用PHPUnit 9.6对Symfony控制器进行功能测试,为避免在每个测试类中重复编写测试用例,创建了包含测试方法的抽象类及抽象的getEndpointConfiguration数据提供者方法。抽象类的两个测试方法均依赖该数据提供者,通过参数中expectedUserClass是否为null来决定执行逻辑,当前用static::markTestSkipped()跳过不符合的测试,但不希望这些测试出现在结果中。尝试拆分数据提供者的方案仍会因空数组产生跳过测试,现寻求彻底忽略这类测试的可行方法。

现有抽象类代码

abstract public function getEndpointConfiguration(): array;

/**
 * @dataProvider getEndpointConfiguration
 * @testdox It grants access without authentication on endpoint $endpoint and method $method
 */
public function testItGrantsAccessWithoutAuthentication(string $method, string $endpoint, ?string $expectedUserClass): void
{
    if ($expectedUserClass !== null) {
        static::markTestSkipped();
    }

    $client = static::createClient();
    $client->request($method, $endpoint);

    static::assertResponseIsSuccessful();
}

/**
 * @dataProvider getEndpointConfiguration
 * @testdox It grants access with JWT token to $expectedUserClass on endpoint $endpoint and method $method
 */
public function testItGrantsAccessWithJwtToken(string $method, string $endpoint, ?string $expectedUserClass): void
{
    if ($expectedUserClass === null) {
        static::markTestSkipped();
    }

    $client = static::createJwtAuthenticatedClient(
        AppFixtures::getUsernameByUserClass($expectedUserClass),
        AppFixtures::getPasswordByUserClass($expectedUserClass)
    );

    $client->request($method, $endpoint);

    static::assertResponseIsSuccessful();
}

控制器测试类代码

public function getEndpointConfiguration(): array
{
    return [
        // 无需认证
        ['GET', '/api/info', null],
        // 需要User类认证
        ['GET', '/api/me', User::class],
    ];
}

可行解决方案

方案1:为每个测试方法单独定义过滤后的数据源

在抽象类中新增两个数据提供者方法,分别对getEndpointConfiguration的结果进行过滤,只保留对应测试方法需要的数据集,这样不符合条件的测试用例根本不会生成,自然不会出现在测试结果中。

修改后的抽象类代码:

abstract public function getEndpointConfiguration(): array;

/**
 * 过滤出无需认证的接口配置
 * @return array
 */
public function getPublicEndpointConfiguration(): array
{
    return array_filter($this->getEndpointConfiguration(), function ($dataset) {
        // 第三个参数为null代表无需认证
        return $dataset[2] === null;
    });
}

/**
 * 过滤出需要JWT认证的接口配置
 * @return array
 */
public function getSecuredEndpointConfiguration(): array
{
    return array_filter($this->getEndpointConfiguration(), function ($dataset) {
        // 第三个参数不为null代表需要对应用户类的认证
        return $dataset[2] !== null;
    });
}

/**
 * @dataProvider getPublicEndpointConfiguration
 * @testdox It grants access without authentication on endpoint $endpoint and method $method
 */
public function testItGrantsAccessWithoutAuthentication(string $method, string $endpoint, ?string $expectedUserClass): void
{
    $client = static::createClient();
    $client->request($method, $endpoint);

    static::assertResponseIsSuccessful();
}

/**
 * @dataProvider getSecuredEndpointConfiguration
 * @testdox It grants access with JWT token to $expectedUserClass on endpoint $endpoint and method $method
 */
public function testItGrantsAccessWithJwtToken(string $method, string $endpoint, ?string $expectedUserClass): void
{
    $client = static::createJwtAuthenticatedClient(
        AppFixtures::getUsernameByUserClass($expectedUserClass),
        AppFixtures::getPasswordByUserClass($expectedUserClass)
    );

    $client->request($method, $endpoint);

    static::assertResponseIsSuccessful();
}

方案说明

  • 两个新增的数据源方法会自动过滤原始数据,只留下对应测试需要的条目,不会生成多余的测试用例。
  • 测试方法无需再写跳过判断逻辑,直接执行核心测试代码即可。
  • 控制器测试类无需任何修改,依然只需要实现getEndpointConfiguration方法。

这样处理后,测试结果中只会显示实际执行的测试用例,完全不会出现被跳过的条目。

内容的提问来源于stack exchange,提问作者Nono

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 01:57:42