Home > Back-end >  Why my dataProvider function in my unit test file is not working properly?
Why my dataProvider function in my unit test file is not working properly?

Time:10-25

I want to test this function:

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;
}

Inside my unit test file, I have these functions:

/**
 * @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',
            '[email protected]'
        ],
        [
            'firstname',
            'Paul'
        ],
        [
            'lastname',
            'Bar'
        ],
        [
            'mobile',
            '0601589540'
        ],
        [
            'postcode',
            '75010'
        ],
        [
            'state',
            'state'
        ],
        [
            'address1',
            'address1'
        ],
        [
            'title',
            'Mr.'
        ]
    ];
}

And finally, I have these errors:

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'

Etc...

I have the impression that my test function (testHandleShouldBeOk) only considers the first array of dataProvider.

I followed this documentation: https://phpunit.readthedocs.io/en/9.5/writing-tests-for-phpunit.html and, I also tried to set yield in dataProvider but, I still have the same errors.

Can you please tell me where I'm wrong?

Thank's in advance.

EDIT: Thank @Alister Bulman, I stopped using a Request mock. I use a real Request object.

It's work:

/**
 * @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', '[email protected]', 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],
    ];
}

CodePudding user response:

You've got 14 different tests being run - one for each part of the data-provider. You are testing each one against 14x fields, and 13 of them won't be set. You can test that (setting all the fields) - or have your test work closer to how it would be expected - returning NULL for anything it doesn't know.

Using a real Request, and not a mock may be helpful here, since it appears to return NULL for things it does not know.

  • Related