Как сделать Test Double для класса RequestHandlerInterface в Zend Expressive, используя Prophesy? - PullRequest
0 голосов
/ 29 августа 2018

Я пытаюсь выполнить модульный тест для метода промежуточного программного обеспечения process() в приложении Zend Expressive. Для этого мне нужно сменить параметр $delegate для метода, который имеет тип RequestHandlerInterface и будет иметь метод handle().

Это должно быть довольно легко сделать, поскольку я успешно издевался с Пророчеством над другими объектами в этом тесте:

Всякий раз, когда вызывается метод handle(), я получаю следующую ошибку: "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 )"

Вот тест. Обратите внимание, что другие mock'ы работают как положено, но метод handle() в $mockDelegate по-прежнему выдает ошибку при его вызове:

/**
 * @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);
}

Вот метод, который он пытается проверить. Кажется, ошибка возникает, когда метод должен делегировать запрос по конвейеру. Смотрите здесь:

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

Как я могу точно высмеять метод RequestHandlerInterface handle() с Пророчеством, чтобы выполнить безошибочный тест?

1 Ответ

0 голосов
/ 31 августа 2018

У вас есть это: $mockDelegate->handle()->willReturn('');, но должно быть что-то вроде этого:

$handler->handle(Argument::that([$mockRequest, 'reveal']))->willReturn('');

В вашем коде вы ожидаете, что handle () будет вызываться без каких-либо аргументов. Но он вызывается с экземпляром интерфейса с поддельными запросами.

Посмотрите на пример из 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()));
}
...