предложения по модульному тестированию исключений - PullRequest
1 голос
/ 20 декабря 2010

Рассмотрим метод, который может выдать исключение с некоторым описательным текстом:

if ($someCondition) {
    throw new \Whatever\Exception('dilithium exhausted');
}

А в другом месте метода есть еще один блок, который может вызвать то же исключение, но с другим текстом:

if ($anotherCondition) {
    throw new \Whatever\Exception('differentialator exploded');
}

При написании модульных тестов для этого класса вы создаете случаи сбоев, чтобы вы могли убедиться, что эти два исключения были выброшены правильно.В этих случаях сбоя вы предпочитаете:

A) Использовать @exceptionExpected в докблоке тестового метода для перехвата универсального класса \ Whwhat \ Exception и впоследствии игнорировать текст getMessage (), предполагая, что вы получили правильный?(Похоже, это плохая идея.)

или:

B) Используйте try / catch и затем подтвердите, что текст getMessage () уловленного исключения равен точной описательной строке, которую вы ожидаете?(Более устойчивый, но это означает изменение ваших тестов всякий раз, когда вы меняете формулировку ошибки.)

или:

C) Создайте отдельное исключение для каждого случая ошибки (например, \ Whwhat \ DilithiumException и \Независимо от \ diffrentialatorException), а затем используйте @exceptionExpected для каждого.

В настоящее время я использую B, но склоняюсь к C. Мне любопытно, что другие делают в этом же сценарии.Есть ли у вас какие-либо рекомендации, которые помогут вам определить: «В какой момент ошибка заслуживает своего собственного класса исключений по сравнению с более общим классом общего доступа?»

Ответы [ 2 ]

2 голосов
/ 05 февраля 2011

PHPUnit также предоставляет @expectedExceptionCode и @expectedExceptionMessage, когда вам нужен этот уровень детализации. Предупреждение: Последнее требует первого.

Кстати, я тоже склоняюсь к А. Если мне нужно выразить больше значения в исключении, я предпочитаю создавать новый класс исключения.Я нахожу сообщение слишком изменчивым, чтобы его можно было протестировать в большинстве приложений.

2 голосов
/ 20 декабря 2010

Все вышеперечисленное.

А - это здорово, и я использую как можно больше, потому что он самый простой. Есть еще один случай, когда A не работает:

/**
 * @exceptionExpected FooException
 */
test() {
  // code that could throw FooException
  ...
  // purpose of the test that throws of FooException
}

В этом случае тест мог пройти, когда он должен был провалиться, потому что он даже не достиг того, что я тестировал. Хороший способ справиться с этим - использовать $ this-> setExpectedException ()

B - это здорово, когда вы действительно можете использовать информацию из исключения. Вместо того, чтобы использовать текст сообщения об исключении, я бы предпочел использовать код. У меня есть исключение проверки формы, которое объединяет все проблемы с данными в одно исключение. Расширяя класс исключений, становится легко передавать большое количество информации из внутреннего состояния ошибки во внешний код обработки.

C выполняет то же самое, что и B, но позволяет упростить код, полагаясь на большее количество классов. Разница между этими двумя тонкими, и я склонен полагаться на эстетику дизайна, чтобы принять решение.

TL; DR: используйте коды исключений, а не сообщения, и разработайте вариант использования, а не модульные тесты.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...