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

单元测试中dataProvider函数工作异常问题排查

PHPUnit数据提供者仅识别首个用例的问题排查与解决

待测试的Handle函数

public function handle(Request $request, Closure $next): mixed
{
    $fields = [
        'address1',
        'address2',
        'address3',
        'city',
        'country',
        'countryName',
        'email',
        'firstname',
        'lastname',
        'mobile',
        'phone',
        'postcode',
        'state',
        'title'
    ];

    foreach ($fields as $field) {
        if ($request->get($field) !== null) {
            return $this->scaActionMiddleware->handle($request, $next);
        }
    }

    /** @var Response $response */
    $response = $next($request);

    return $response;
}

原测试代码

/**
 * @dataProvider dataProvider
 */
public function testHandleShouldBeOk(string $input, string $value): void
{
    $request = $this->createMock(Request::class);
    $response = $this->createMock(JsonResponse::class);
    $next = (function () use ($response) {
        return $response;
    })(...);

    $request->expects(self::any())
        ->method('get')
        ->with($input)
        ->willReturn($value);

    $this->scaActionMiddleware->expects(self::once())
        ->method('handle')
        ->with($request, $next);

    $this->scaActionUserMiddleware->handle($request, $next);
}

/**
 * @return string[][]
 */
private function dataProvider(): array
{
    return [
        [
            'address1',
            '80 boulevard magenta'
        ],
        [
            'address2',
            '22 rue du Commerce'
        ],
        [
            'address3',
            '124 avenue des Champs'
        ],
        [
            'city',
            'Paris'
        ],
        [
            'country',
            'FR'
        ],
        [
            'countryName',
            'France'
        ],
        [
            'email',
            'my-mail@email.com'
        ],
        [
            'firstname',
            'Paul'
        ],
        [
            'lastname',
            'Bar'
        ],
        [
            'mobile',
            '0601589540'
        ],
        [
            'postcode',
            '75010'
        ],
        [
            'state',
            'state'
        ],
        [
            'address1',
            'address1'
        ],
        [
            'title',
            'Mr.'
        ]
    ];
}

测试报错信息

Expectation failed for method name is "get" when invoked zero or more
times Parameter 0 for invocation
Illuminate\Http\Request::get('address1', null): mixed does not match
expected value. Failed asserting that two strings are equal. Expected
:'address2' Actual :'address1'

Expectation failed for method name is "get" when invoked zero or more
times Parameter 0 for invocation
Illuminate\Http\Request::get('address1', null): mixed does not match
expected value. Failed asserting that two strings are equal. Expected
:'address3' Actual :'address1'

问题原因

原测试使用Request Mock时,给get方法设置了仅接收指定参数$input的断言,但待测试的handle函数会循环遍历所有字段,依次调用$request->get($field)。比如测试第二个用例(address2)时,代码会先调用get('address1'),而Mock的get方法只期望接收address2,导致参数匹配失败,触发报错。

解决方法

停止使用Request Mock,改用真实的Request对象,这样get方法能正确返回对应字段的值,不会出现参数匹配限制。修改后的测试代码如下:

/**
 * @dataProvider dataProvider
 *
 * @throws ConnectDbAccessException
 * @throws JwtServiceException
 * @throws ConfigServiceException
 * @throws ScaServiceException
 * @throws SerializerServiceException
 */
public function testHandleShouldBeOk(string $field, string $value, int $invoke): void
{
    $request = Request::create('foo', 'POST', [$field => $value]);
    $next = function () {
        return $this->createMock(Response::class);
    };

    $this->scaActionMiddleware->expects(self::exactly($invoke))
        ->method('handle')
        ->with($request, $next);

    $this->scaActionUserMiddleware->handle($request, $next);
}

/**
 * @return array<int, array<int, int|string>>
 */
private function dataProvider(): array
{
    return [
        ['address1', '80 boulevard magenta', 1],
        ['address2', '22 rue du Commerce', 1],
        ['address3', '124 avenue des Champs', 1],
        ['city', 'Paris', 1],
        ['country', 'FR', 1],
        ['countryName', 'France', 1],
        ['email', 'my-mail@email.com', 1],
        ['firstname', 'Paul', 1],
        ['lastname', 'Bar', 1],
        ['mobile', '0601589540', 1],
        ['postcode', '75010', 1],
        ['state', 'state', 1],
        ['address1', 'address1', 1],
        ['title', 'Mr.', 1],
        ['foo', '80 boulevard magenta', 0],
    ];
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 06:40:26