Модульный тест контроллера в slim3

В начале хочу сказать - я новичок в модульном тестировании в PHP (phpunit). В моем новом проекте (slim3 framework) я хотел бы протестировать свои контроллеры, например, LoginController.

Моя идея (в методе модульного тестирования)

  • Создать экземпляр LoginController
  • Макет некоторых сервисов в контроллере (DI)
  • Выполнить метод, который является ответом на запрос (в моем методе контроллеров __invoke)

Моя проблема связана с параметрами для метода __invoke. В Slim3 вызываемый метод запроса имеет два первых параметра:

RequestInterface $request и ResponseInterface $response

Как я могу создать эти параметры в своем классе модульного тестирования? Я искал несколько примеров для этой проблемы, но безуспешно.

Какие-либо предложения?

Я нашел код в тестах Slim3 для имитации запроса:

protected function requestFactory()
{
    $uri = Uri::createFromString('https://example.com:443/foo/bar?abc=123');
    $headers = new Headers();
    $cookies = array(
        'user' => 'john',
        'id' => '123',
    );
    $env = Slim\Http\Environment::mock();
    $serverParams = $env->all();
    $body = new Body(fopen('php://temp', 'r+'));
    $request = new Request('GET', $uri, $headers, $cookies, $serverParams, $body);

    return $request;
}

Но я не уверен, что это хороший способ.

Спасибо за любую помощь


person robertw    schedule 19.03.2016    source источник


Ответы (1)


Я написал одно решение здесь: https://akrabat.com/testing-slim-framework-actions/

Я использую Environment::mock() для создания $request, а затем запускаю действие. Делая каждый маршрут вызываемым классом, в конструктор которого все зависимости внедряются, все это также становится намного проще.

По сути, тест выглядит так:

class EchoActionTest extends \PHPUnit_Framework_TestCase
{
    public function testGetRequestReturnsEcho()
    {
        // instantiate action
        $action = new \App\Action\EchoAction();

        // We need a request and response object to invoke the action
        $environment = \Slim\Http\Environment::mock([
            'REQUEST_METHOD' => 'GET',
            'REQUEST_URI' => '/echo',
            'QUERY_STRING'=>'foo=bar']
        );
        $request = \Slim\Http\Request::createFromEnvironment($environment);
        $response = new \Slim\Http\Response();

        // run the controller action and test it
        $response = $action($request, $response, []);
        $this->assertSame((string)$response->getBody(), '{"foo":"bar"}');
    }
}
person Rob Allen    schedule 20.03.2016
comment
Это отлично сработало для меня! Спасибо @rob (решение, написанное на вашем веб-сайте, тоже было полезно) - person Cody-PHP-jQuery; 09.04.2016
comment
Спасибо за этот код, @rob-allen! Как бы вы предложили нам сделать что-то подобное, если бы наши маршруты определялись через анонимные функции? (Например: $app->get("/test/{id}", function($request, $response, $args) { ... });) - person rinogo; 07.07.2016
comment
Я понял. Для тех, кому интересно, вам нужно превратить вашу анонимную функцию в именованную функцию (например, echo_action()). Затем вместо $action = new \App\Action\EchoAction(); используйте $action = "echo_action"; - person rinogo; 07.07.2016
comment
Спасибо за заметки @ringo. Тестировать анонимные функции сложно - person Rob Allen; 07.07.2016