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', 'my-mail@email.com' ], [ '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 IlluminateHttpRequest::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 IlluminateHttpRequest::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', '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], ]; }
Advertisement
Answer
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.