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]

Понравилась статья? Расскажите о ней друзьям:

Метки: PHP, кодинг

Комментарии
Для работы модуля комментариев включите javaScript


Показать/скрыть правила
Имя
[i] [b] [u] [s] [url]
:-) ;-) :D *lol* 8-) :-* :-| :-( *cry* :o :-? *unsure* *oops* :-x *shocked* *zzz* :P *evil*

Осталось 1000 символов.
Код защиты от спама Обновить код
Каждый комментарий проходит ручную модерацию. 100% фильтрация спама.
Продвижение
Время
Метки