Упрощенный подход к тестированию политик в Laravel
И тесты тоже стали немного быстрее.
Большинство тестов — это функциональные тесты. Нам нравится уверенность в том, что можно смоделировать весь жизненный цикл запроса и ответа. Это включает такие вещи, как авторизация и валидация.
Таким образом, если политика запрещала пользователя на основании какого-то условия, я устанавливал именно такого пользователя, делал обычный запрос и утверждал, что ответ будет 403 Forbidden
. Это довольно хорошо работало, но в одном из проектов я столкнулся с проблемой, усложнившей этот подход.
Условие политики, которое нужно было проверить, также частично выполнялось в middleware, подключенном к маршруту. Поэтому я не мог быть уверен в том, что логика политики выполняется, поскольку middleware отклоняло её до того, как политика была оценена.
Я мог бы удалить middleware динамически с помощью хелпера `withoutMiddleware
, но тогда это стало бы похоже на грязный тест.
Вместо этого я попробовал другой подход. В одном из функциональных тестов я просто утверждаю, что политика подключена к нужному методу:
// внутри метода теста $policyMock = $this->partialMock(SomePolicy::class); $policyMock->expects('viewAny')->andReturnFalse(); // теперь выполним обычный тестовый запрос и assertForbidden
Это даёт уверенность в том, что контроллер подключён к правильному методу политики. Если кто-то удалит или изменит авторизацию политики, тест будет провален из-за отсутствующего ожидания имитации.
Затем, для актуальной логики политики, я могу написать простые тесты, создающие экземпляр политики и утверждающие логику метода напрямую:
$userWithoutTheRightPermissions = User::factory()->create(/* настройка здесь */); $this->assertFalse((new SomePolicy)->viewAny($userWithoutTheRightPermissions));
Этим тестам не нужно задавать так много данных, и мне не нужно имитировать HTTP-запрос через фреймворк. Они быстрые, легкие, и их можно тестировать напрямую, не беспокоясь о middleware.
Необходимо уделить этому больше времени в проекте, прежде чем выносить окончательное суждение, но пока мне очень нравится этот подход. Он решает весьма специфическую проблему, когда происходит дублирование авторизации, навязанной middleware, и политиками.