Тестирование API контроллеров в Laravel

Pavel Buchnev
2 min readJun 24, 2020

--

Очень часто приходится писать тесты для API различных приложений и поэтому за долгое время накопилась парочка приемов, которыми хотелось бы поделиться.

Подготовка

  1. При разработке API я придерживаюсь практики создания Single Action Controllers, т.е. один контроллер имеет лишь один экшен, если наглядно, то выглядит как то так
Controllers
- Users
- UpdateAction.php
- CreateAction.php
- IndexAction.php
- Profile
- UpdatePasswordAction.php
- ...
- News
- IndexAction.php
- MarkAsReadAction.php
- ...
...

Это позволяет мне легко ориентироваться в тех действиях, которые имее тот или иной раздел или модуль, а также не раздувать контроллеры. Плюс ко всему это удобно тестировать, т.к. стурктура тестов может повторять структуру экшенов

Controllers
- Users
- UpdateActionTest.php
- CreateActionTest.php
- IndexActionTest.php
- Profile
- UpdatePasswordActionTest.php
- ...
- News
- IndexActionTest.php
- MarkAsReadActionTest.php
- ...
...

2. Каждый экшен имеет свой уникальный Route name, который является единственным источником для генерации URL для конкретного Route.

Приступим к написанию тестов

Т.к. я использую Single Action Controllers, то каждый контроллер по сути представлен одним TestCase, поэтому для тестирования можно создать отдельный TestCase, который помогал бы упростить процесс покрытия функционала тестами. Я назвал его ActionTestCase

Данный тест кейс имеет единственный обязательный метод getRouteName, который должен возвращать название роута для которого пишем тест. Данное имя позволяет в реестре роутов найти подходящий по имени и получить все необходимые данные для выполнения запросов.

Вот пример тестирования регистрации пользователя

И пример для тестирования авторизованного пользователя

А теперь немного расскажу, что про методы. Для себя я выявил несколько методов, которые мне помогают упростить рутинную работу:

  1. Имя роута я прописываю всего один раз
  2. По названию роута я нахожу нужный Route и определяю тип запроса, его наличие, а также я могу получить middleware, которые используются и также протестировать их наличие.
  3. При выполении запросов мне не нужно каждый раз указывать URL

Методы:

assertRouteContainsMiddleware(…$names)
Проверка на наличие в роуте переданных middleware.

assertRouteHasExactMiddleware(…$names)
Проверка на то, что роут содержит только указанные middleware.

getRouteByName(): Route
Получение объекта текущего роута. Если роут не найдет, то тест будет помечен как fail

callRouteAction(array $data = [], array $parameters = [], array $headers = []): TestResponse
Выполнение запроса от неавторизованного пользователя.
$data — Request body
$paramenters — Route parameters
$headers — Request headers

callAuthorizedRouteAction(array $data = [], array $parameters = [], array $headers = [], array $scopes = []): TestResponse
Выполнение авторизованного запроса. В момент запроса создается рандомный пользователь и от него выполняется запрос

callAuthorizedByUserRouteAction(User $user, array $data = [], array $parameters = [], array $headers = [], array $scopes = []): TestResponse
Выполнение запроса от имени переданного пользователя.

Ну вот собственно и все. Этих методов достаточно для выполнения повседневных рутинных операций.

Надеюсь моя статья будет полезна и сподвигнет вас на написание своих велосипедов. Делитесь своим опытом в комментариях, будет интересно почитать!

Мои статьи по Laravel

--

--

Pavel Buchnev
Pavel Buchnev

Written by Pavel Buchnev

Senior PHP Developer | Contributor to Spiral Framework 🚀 | Enthusiast of RoadRunner & long-running applications | Creator of Buggregator

No responses yet