I'm trying to make a unit test for the process()
method of a middleware in a Zend Expressive application. To do this, I need to mock the out the $delegate
parameter for the method which is of type RequestHandlerInterface
and will have the method handle()
.
This should be pretty easy to do as I've mocked successfully with Prophesy on other objects in this test:
Whenever the handle()
method gets called, I receive the following error: "Unexpected method call on Double\RequestHandlerInterface\P18:\n - handle(\n Double\ServerRequestInterface\P17:000000004a01de0d000000000617c05e Object (\n 'objectProphecy' => Prophecy\Prophecy\ObjectProphecy Object (*Prophecy*)\n )\n )\nexpected calls were:\n - handle(\n\n )"
Here's the test. Note that other mocks are working as expected but the handle()
method on the $mockDelegate
still throws the error when it is called:
/**
* @test
*/
public function
testReturnsRedirectResponseForHandlerWhenNoErrorsFoundRequestTypePOST()
{
$renderer = $this->prophesize(TemplateRendererInterface::class);
$renderer
->render('app::contract-form-page', [])
->willReturn('');
$validateSubmitAction = new ValidateSubmitAction(
$this->router->reveal(),
$renderer->reveal(),
get_class($this->container->reveal()),
$this->logger->reveal()
);
$mockRequest = $this->prophesize(ServerRequestInterface::class);
$mockRequest->getMethod()->willReturn('POST');
$mockRequest->getBody()->willReturn(
//create fake object with getContents method
new class {
public function getContents(){ return 'location-number=testLoc&contract-number=1234';}
});
$mockDelegate = $this->prophesize(RequestHandlerInterface::class);
$mockDelegate->handle()->willReturn('');
$response = $validateSubmitAction->process(
$mockRequest->reveal(),
$mockDelegate->reveal()
);
$this->assertInstanceOf(ValidateSubmitAction::class, $validateSubmitAction);
}
Here's the method it is trying to test. The error seems to occur when the method is supposed to delegate the request down the pipeline. See here:
public function process(ServerRequestInterface $request, RequestHandlerInterface $delegate): ResponseInterface
{
...
// Delegate on to the handler
return $delegate->handle($request); //<-- this is where the error occurs in the unit test
How can I accurately mock the RequestHandlerInterface handle()
method with Prophesy so as to achieve an error-free test?
You have this: $mockDelegate->handle()->willReturn('');
, but it should be something like this this:
$handler->handle(Argument::that([$mockRequest, 'reveal']))->willReturn('');
In your code you expect handle() to be called without any arguments. But it's called with an instance of the mocked request interface.
Have a look at an example from zend-expressive-session:
public function testMiddlewareCreatesLazySessionAndPassesItToDelegateAndPersistsSessionInResponse()
{
$request = $this->prophesize(ServerRequestInterface::class);
$request
->withAttribute(SessionMiddleware::SESSION_ATTRIBUTE, Argument::type(LazySession::class))
->will([$request, 'reveal']);
$response = $this->prophesize(ResponseInterface::class);
$handler = $this->prophesize(RequestHandlerInterface::class);
$handler->handle(Argument::that([$request, 'reveal']))->will([$response, 'reveal']);
$persistence = $this->prophesize(SessionPersistenceInterface::class);
$persistence
->persistSession(
Argument::that(function ($session) use ($persistence, $request) {
$this->assertInstanceOf(LazySession::class, $session);
$this->assertAttributeSame($persistence->reveal(), 'persistence', $session);
$this->assertAttributeSame($request->reveal(), 'request', $session);
return $session;
}),
Argument::that([$response, 'reveal'])
)
->will([$response, 'reveal']);
$middleware = new SessionMiddleware($persistence->reveal());
$this->assertSame($response->reveal(), $middleware->process($request->reveal(), $handler->reveal()));
}