Утверждение исключений в тестах Laravel 11

Источник: «Asserting Exceptions in Laravel Tests»
Как тестировать ожидаемые исключения, имитировать обработку исключений в Laravel 11 и использовать фасад Laravel Exceptions для утверждения исключений в HTTP-тестах.

В недавнем релизе Laravel 11.4 появился фасад Exceptions, добавляющий удобства для утверждения исключений в обработчике исключений Laravel. До этого релиза обычно использовали $this->withoutExceptionHandling(), чтобы подтвердить, что определённое исключение произошло во время HTTP-теста:

use App\Exceptions\WelcomeException;

$this->withoutExceptionHandling();

try {
$this->get('/');
} catch (WelcomeException $e) {
$this->assertEquals('Woops, there was an issue with your request!', $e->getMessage());

return;
}

$this->fail(sprintf('The expected "%s" exception was not thrown.', WelcomeException::class));

Когда ожидается, что запрос не будет выбрасывать никаких исключений, использование withoutExceptionHandling избавляет от посредника при отладке того, почему возникает ошибка, когда этого не ожидаешь. Приведённый выше код очень утомителен, потому что он вручную перехватывает исключение, создаёт утверждения об исключении и вызывает return, чтобы избежать ручного вызова $this->fail(). Вручную отлавливаются ситуации, когда тест не выбрасывает исключение, когда оно ожидается.

Если в приведённом сценарии вызвать $this->fail(), то результат будет выглядеть так:

phpunit

There was 1 failure:

1) Tests\Feature\ExampleTest::test_the_application_returns_a_successful_response
The expected "App\Exceptions\WelcomeException" exception was not thrown.

/app/tests/Feature/ExampleTest.php:33

Фасад Exceptions в Laravel 11

Давайте посмотрим, как новый фасад Exceptions может упростить тест; первый пример, переписанный заново, будет выглядеть так:

use Illuminate\Support\Facades\Exceptions;

Exceptions::fake();

$this->get('/');

Exceptions::assertReported(function (WelcomeException $e): bool {
return $e->getMessage() === "Woops, there was an issue with your request!";
});

Использование фасада Exceptions даёт бонус в виде отсутствия необходимости перехватывать исключение для утверждения вручную. Другими словами, тест может сохранить обработчик исключений Laravel на месте, но при этом иметь возможность утверждать исключения, произошедшие во время запроса.

Если необходимо убедиться, что тест не выбросит определённое исключение или не выбросит ни одного исключения вообще, новый фасад нас прикроет:

Exceptions::assertNotReported(WelcomeException::class);

Exceptions::assertNothingReported();

Если обработчик исключений не сообщает о WelcomeException, тестовый вывод выдаст красиво оформленное сообщение:

phpunit

There was 1 failure:

1) Tests\Feature\ExampleTest::test_the_application_returns_a_successful_response
The expected [App\Exceptions\WelcomeException] exception was not reported.

Хотя бывают случаи, когда не хочется имитировать обработчик исключений Laravel, при тестировании граничных ситуаций новый фасад Exceptions очень полезен и очищает код:

Exceptions::assertReported(WelcomeException::class);
Exceptions::assertReportedCount($count);
Exceptions::assertNotReported(WelcomeException::class);
Exceptions::assertNothingReported();
Exceptions::throwFirstReported();

Более подробную информацию о фасаде Exceptions можно найти в документации Laravel.

Дополнительные материалы

Предыдущая Статья

Текущая ветвь/current branch в git

Следующая Статья

Селекторы атрибутов в CSS