Я думаю, що на це питання потрібна оновлена відповідь, оскільки більшість відповідей тут досить застарілі.
Перш за все до питання ОП:
Я думаю, що досить добре прийнято, що введення в JUnit концепції "очікуваного перевищення" було поганим кроком, оскільки цей виняток можна було застосувати де завгодно, і він пройде тест. Це працює, якщо ви кидаєте (і заявляєте) про винятки, специфічні для домену, але я викидаю такі види винятків лише тоді, коли я працюю над кодом, який повинен бути абсолютно бездоганним, - більшість APIS просто викине вбудовані винятки, як IllegalArgumentException
або IllegalStateException
. Якщо два виклики, які ви робите, могли б потенційно викликати ці винятки, тоді @ExpectedException
анотація буде зеленим кольором для вашого тесту, навіть якщо це неправильний рядок, який видає виняток!
Для цієї ситуації я написав клас, який, напевно, писали багато хто з нас, це assertThrows
метод:
public class Exceptions {
private Exceptions(){}
public static void assertThrows(Class<? extends Exception> expectedException, Runnable actionThatShouldThrow){
try{
actionThatShouldThrow.run();
fail("expected action to throw " + expectedException.getSimpleName() + " but it did not.");
}
catch(Exception e){
if ( ! expectedException.isInstance(e)) {
throw e;
}
}
}
}
цей метод просто повертається, якщо вилучено виняток, що дозволяє вам робити подальші твердження / перевірку у вашому тесті.
з синтаксисом Java 8 ваш тест виглядає дуже приємно. Нижче наведено один із найпростіших тестів на нашій моделі, який використовує метод:
@Test
public void when_input_lower_bound_is_greater_than_upper_bound_axis_should_throw_illegal_arg() {
AxisRange range = new AxisRange(0,100);
Runnable act = () -> range.setLowerBound(200);
assertThrows(IllegalArgumentException.class, act);
}
ці тести є трохи хиткими, тому що крок "діяти" насправді не виконує жодної дії, але я думаю, що сенс все ще досить чіткий.
є також крихітна маленька бібліотека на maven, яка називається catch-exception, яка використовує синтаксис у стилі mockito, щоб перевірити, чи викидаються виключення. Це виглядає красиво, але я не шанувальник динамічних проксі. Тим не менш, синтаксис настільки витончений, що залишається спокусливим:
List myList = new ArrayList();
catchException(myList).get(1);
assert caughtException() instanceof IndexOutOfBoundsException;
Нарешті, для ситуації, з якою я зіткнувся, щоб дістатися до цього потоку, існує спосіб ігнорувати тести, якщо виконується якась кондоніція.
Зараз я працюю над тим, щоб викликати деякі бібліотеки DLL через Java-бібліотеку для завантаження під назвою JNA, але наш сервер збірки знаходиться в ubuntu. Мені подобається намагатися керувати подібним розвитком за допомогою тестів JUnit - хоча вони на даний момент далеко не "одиниці". Що я хочу зробити, це запустити тест, якщо я на локальній машині, але ігнорувати тест, якщо ми працюємо в ubuntu. JUnit 4 має для цього положення, яке називається Assume
:
@Test
public void when_asking_JNA_to_load_a_dll() throws URISyntaxException {
Assume.assumeFalse(BootstrappingUtilities.isCircleCI());
URL url = DLLTestFixture.class.getResource("USERDLL.dll");
String path = url.toURI().getPath();
path = path.substring(0, path.lastIndexOf("/"));
NativeLibrary.addSearchPath("USERDLL", path);
Object dll = Native.loadLibrary("USERDLL", NativeCallbacks.EmptyInterface.class);
assertThat(dll).isNotNull();
}