В современном веб‑разработке тестирование middleware становится ключевым этапом обеспечения надёжности и безопасности приложений. Особенно актуально это при работе с Yii2 2.0.40, где middleware реализует промежуточную логику, от проверки авторизации до логирования запросов. В этой статье мы разберём, как тестировать пользовательский middleware в Yii2 2.0.40, используя PHPUnit, мокировать запросы и ответы, а также проверять редиректы. Пошаговый пример поможет быстро внедрить QA‑процессы в ваш проект без лишних усилий.
Разбор задачи
Предположим, у нас есть middleware, который проверяет наличие токена в заголовке запроса и при его отсутствии перенаправляет пользователя на страницу логина. Тестируемая логика должна обрабатывать два сценария: корректный токен – запрос проходит дальше, токен отсутствует – генерируется редирект. Для проверки нам понадобится создать mock‑объекты запроса и ответа, а также убедиться, что middleware корректно взаимодействует с компонентом Yii::$app->response.
Пошаговое решение
1. Создаём класс теста, наследуемый от PHPUnitFrameworkTestCase. Внутри определяем метод setUp(), где инициализируем приложение Yii2 в режиме тестирования, подключаем необходимые компоненты и создаём экземпляр middleware. 2. Для mock‑объекта запроса используем Yii::$app->createRequest() и подменяем заголовки, чтобы симулировать наличие или отсутствие токена. 3. Мокаем объект ответа через PHPUnit’s createMock, чтобы перехватить вызовы setStatusCode, redirect и getHeaders. 4. В первом тесте передаём запрос с валидным токеном, вызываем middleware и проверяем, что статус ответа остаётся 200, а редирект не был вызван. 5. Во втором тесте отправляем запрос без токена, проверяем, что метод redirect был вызван с URL логина, а статус кода установлен в 302. 6. Для проверки редиректа используем assertion containsHeader(‘Location’, ‘/login’) и убедимся, что middleware правильно редиректит пользователя. 7. После выполнения каждого теста очищаем состояние приложения, чтобы избежать конфликтов между тестами. В результате вы получите надёжный набор unit‑тестов, покрывающих критические пути вашего middleware.
Рабочий код
headers->set('X-Middleware', 'Applied');
return $response;
}
}
class MiddlewareTest extends TestCase
{
public function testMiddlewareAddsHeader()
{
// Создаём имитацию приложения
$app = new Application(['id' => 'test-app']);
// Mock запроса
$request = new Request();
$request->setPathInfo('/test');
// Mock ответа
$response = new Response();
// Регистрируем middleware
$app->on(Application::EVENT_BEFORE_REQUEST, function ($event) {
$event->request->middleware = new SampleMiddleware();
});
// Запускаем middleware вручную
$middleware = new SampleMiddleware();
$res = $middleware->handle($request, function () use ($response) {
return $response;
});
// Проверяем наличие заголовка
$this->assertEquals('Applied', $res->headers->get('X-Middleware'));
}
}
Типичные ошибки
- Неправильный порядок регистрации middleware – он должен добавляться до обработки запроса.
- Отсутствие mock‑объектов – без имитации Request и Response тест не увидит изменения.
- Использование $app->run() в тесте – это вызывает реальный цикл, а не unit‑тест.
- Неправильный тип callback – вместо функции должен быть объект Response.
FAQ
Как mock‑ить Request и Response?
Используйте классы yiiwebRequest и yiiwebResponse, но не инстанцируйте напрямую через Yii::$app. Создайте объекты вручную, задав pathInfo и необходимые заголовки.
Можно ли тестировать middleware без приложения?
Да, но нужно передавать в handle() настоящий Request и функцию‑замыкание, возвращающую Response. Это избавит от зависимости от глобального $app.
Что делать, если middleware зависит от компонентов (Redis, DB)?
Создайте mock‑компоненты и установите их в $app->components, либо используйте dependency injection через конструктор. В тесте мокайте только нужные методы.
Заключение
Тестирование middleware в Yii2 2.0.40 с PHPUnit – это просто, если следовать шагам: mock‑ить Request/Response, регистрировать middleware вручную, проверять изменения. Ниже чек‑лист.
- Создать новый тестовый класс, расширяющий PHPUnitFrameworkTestCase.
- Инициализировать Request и Response без использования Yii::$app.
- Регистрировать middleware через событие или напрямую в handle().
- Использовать замыкание, возвращающее Response.
- Проверять изменённые заголовки, статус, тело и др.
- Отделять unit‑тесты от интеграционных – не использовать $app->run().
