Давайте посмотрим на такой совершенно простой пример, как этот:
<?PHP
namespace App;
class Example
{
public function handle()
{
throw new \Exception('Not Found', 404);
}
}
Начиная с PHPunit 9.0 и далее аннотация expectedException была признана устаревшей и удалена.
Теперь мы можем сосредоточиться на существующих решениях.
Попробуй поймать
Во-первых, это пара try-catch. Я видел, как Адам Уотан использовал его и защищал его в своем курсе TDD. Некоторые разработчики считают это большим старомодным. Однако у него есть одно преимущество. Внутри блока catch вы можете запустить дополнительное условие, связанное с исключением или даже некоторыми другими частями кода, например, пользователь не был обновлен.
/** @test*/
function exception_is_thrown()
{
try {
$example = new Example();
$example->handle();
} catch (\Exception $e) {
$this->assertSame('Not Found', $e->getMessage());
$this->assertSame(404, $e->getCode());
// additional assertion e.g. user wasn't updated
return;
}
$this->fail('Exception was not thrown.');
}
Ожидания исключения
Этот подход является рекомендуемым PHPunit. Вы можете использовать четыре различных метода expectException
, expectExceptionMessage
, expectExceptionMessageMatches
. Имейте в виду, что, кроме этих 4, Вы не можете использовать никаких других условий. Если вы добавите $this->assertTrue(false);
он будет проигнорирован в конце теста.
/** @test */
function exception_is_thrown()
{
$this->expectException(\Exception::class);
$this->expectExceptionCode(404);
$this->expectExceptionMessage('Not Found');
$this->expectExceptionMessageMatches('/Found/');
$example = new Example();
$example->handle();
}
Вывод
Оба варианта являются отличными стратегиями для тестирования исключений PHP. Лично я использую второй вариант по умолчанию. Я бы использовал первый вариант только в том случае, если необходимы дополнительные условия.