PHPUnit. Тестирование исключений
версия для печатиPHPUnit 5.6, метод expectException(), а так же директива @expectedException используются в тестах для указания ядру фреймворка "ожидать такое-то исключение". В итоге тест считается пройденным если исключение возникло.
И тут есть ньюансик: после того, как PHPUnit поймает ожидаемое исключение, выполнение тест-метода прекратится! Т.е. expectException() - это аналог assert-метода, только с прерыванием. Есть так же методы на проверку кода и сообщения исключения.
Но как быть, если нужно протестировать метод на нормальное поведение и на возникновение исключений? Вариантов несколько:
- писать тест-методы на нормальное поведение и на каждое пробрасываемое исключение отдельно;
- в тест-методе оформлять блоки try...catch;
- использовать data provider.
Пример (сильно утрированный): ищем степень двойки, при условии, что показатель степени - положительное целое число.
namespace app;
class Power
{
/**
* Метод находит степень двойки, при условии, что показатель степени - положительное
* целое число
* @param int $power показатель степени
* @return int
* @throws \InvalidArgumentException
* @throws \UnexpectedValueException
*/
public static function intPowerOfTwo($power)
{
if (!is_int($power)) {
throw new \InvalidArgumentException('Степень должна быть целым числом');
} else if ($power <= 0) {
throw new \UnexpectedValueException('Степень должна быть положительным целым числом');
}
return 2**$power;
}
}
Как видно из примера, есть три ситуации - нормальное завершение метода и два разных исключения. Написать три тест-метода на каждый случай - не проблема. А чтобы протестировать этот метод полностью в одном тесте, понадобится такой код:
use app\Power;
class PowerTest extends PHPUnit\Framework\TestCase
{
public function test_intPowerOfTwo()
{
$result = Power::intPowerOfTwo(3);
$this->assertEquals(8, $result, 'Неверный результат вычисления');
try {
Power::intPowerOfTwo('bad');
$this->fail('Не проброшено исключение на неверный тип параметра');
} catch (\InvalidArgumentException $e) { }
try {
Power::intPowerOfTwo(-4);
$this->fail('Не проброшено исключение на отрицательный показатель степени');
} catch (\UnexpectedValueException $e) { }
}
}
Третий вариант - используем data provider.
use app\Power;
class PowerTest extends PHPUnit\Framework\TestCase
{
/**
* @dataProvider powerProvider
*/
public function test_intPowerOfTwo($power, $expected, $message, $exception)
{
if ($exception) {
$this->expectException($exception);
}
$result = Power::intPowerOfTwo($power);
$this->assertEquals($expected, $result, $message);
}
public function powerProvider()
{
return [
'norm' => [3, 8, 'Двойка в третьей степени', null,],
'wrong type' => ['bad', null, 'Неверный тип параметра', \InvalidArgumentException::class],
'not positive' => [-4, null, 'Отрицательный показатель степени', \UnexpectedValueException::class],
];
}
}
[1oo%, EoF]Понравилась статья? Расскажите о ней друзьям: