Ответ 1
В других ответах была рассмотрена общая проблема написания unit test, которая проверяет, что генерируется исключение. Но я думаю, что ваш вопрос действительно спрашивает о том, как заставить код генерировать исключение в первую очередь.
Возьмите свой код в качестве примера. Было бы очень сложно заставить ваш getServerName()
внутренне генерировать исключение в контексте простого unit test. Проблема заключается в том, что для того, чтобы исключение произошло, код (обычно) должен выполняться на машине, чья сеть нарушена. Упорядочить, что это произойдет в unit test, вероятно, невозможно... вам нужно было бы неправильно настроить машину перед запуском теста.
Так в чем же ответ?
-
В некоторых случаях простой ответ заключается только в том, чтобы принять прагматическое решение, а не идти на полное покрытие тестов. Хороший пример - ваш метод. Из проверки кода должно быть ясно, что на самом деле делает этот метод. Тестирование это ничего не докажет (кроме ниже
**
). Все, что вы делаете, - это улучшить количество проверок и номера тестовых покрытий, ни одна из которых не должна быть целью проекта. -
В других случаях может быть разумным разделить низкоуровневый код, в котором генерируется исключение, и сделать его отдельным классом. Затем, чтобы проверить обработку кода более высокого уровня для исключения, вы можете заменить класс макетным классом, который выведет нужные исключения.
Вот ваш пример с учетом этого "лечения". (Это немного надуманно...)
public interface ILocalDetails {
InetAddress getLocalHost() throws UnknownHostException;
...
}
public class LocalDetails implements ILocalDetails {
public InetAddress getLocalHost() throws UnknownHostException {
return InetAddress.getLocalHost();
}
}
public class SomeClass {
private ILocalDetails local = new LocalDetails(); // or something ...
...
public String getServerName() {
try {
InetAddress addr = local.getLocalHost();
return addr.getHostName();
}
catch (Exception e) {
e.printStackTrace();
return "";
}
}
}
Теперь до unit test вы создаете "макет" реализации интерфейса ILocalDetails
, метод getLocalHost()
выдает исключение, которое вы хотите в соответствующих условиях. Затем вы создаете единичный текст для SomeClass.getServerName()
, устанавливая, что экземпляр SomeClass
использует экземпляр вашего класса "mock" вместо обычного. (Последний бит может быть выполнен с использованием фальшивой структуры, выставляя setter
для атрибута local
или используя API отражения.)
Очевидно, что вам нужно будет изменить свой код, чтобы он выглядел таким образом. И есть ограничения на то, что вы можете сделать... например, теперь вы не можете создать unit test, чтобы сделать реальный метод LocalDetails.getLocalHost()
для исключения. Вы должны принять индивидуальное решение относительно того, стоит ли это делать; то есть преимущество unit test перевешивает работу (и дополнительную сложность кода), позволяя таким образом тестировать класс. (Тот факт, что в конце этого есть метод static
, является большой частью проблемы.)
**
Существует гипотетический момент для такого тестирования. В вашем примере тот факт, что исходный код ловит исключение и возвращает пустую строку, может быть ошибкой... в зависимости от того, как специфицирован API-метод метода... и гипотетический unit test подхватил бы его. Однако в этом случае ошибка настолько вопиющая, что вы заметили ее при написании unit test! Предполагая, что вы исправляете ошибки по мере их нахождения, unit test становится несколько избыточным. (Вы не ожидали, что кто-то повторит эту ошибку...)