Проверить что код ведет себя корректно в штатных ситуациях важно. Но также важно проверить, что он ведет себя корректно и в нештатных ситуациях. Рассмотрим код
new ArrayList<Object>().get(0);
Этот код должен генерировать IndexOutOfBoundsException. Аннотация @Test
имеет необязательный параметр "expected
" значением которого должен быть наследник Throwable
. Если мы хотим проверить, что ArrayList
генерирует корректное исключение, мы можем написать:
@Test(expected = IndexOutOfBoundsException.class)
public void empty() {
new ArrayList<Object>().get(0);
}
Данный подход полезен в простых случаях, но он имеет существенные ограничения. Для примера, вы не можете проверить значение message в исключении exception, или состояние бизнес-объекта после того, как исключение было сгенерировано.
Try/Catch Идиома
В этом случае вы можете использовать try/catch идиому которая превалировала в JUnit 3.x:
@Test
public void testExceptionMessage() {
try {
new ArrayList<Object>().get(0);
fail("Expected an IndexOutOfBoundsException");
} catch (IndexOutOfBoundsException ex) {
assertThat(ex.getMessage(), is("Index: 0, Size: 0"));
}
}
ExpectedException Rule
В качестве альтернативы вы можете использовать
ExpectedException
rule. Это "правило" позволяет вам не только обозначить какое исключение Вы ожидаете, но также и какое сообщение в нем должно быть:@Rule
public ExpectedException thrown = ExpectedException.none();
@Test
public void shouldTestExceptionMessage() throws IndexOutOfBoundsException {
thrown.expect(IndexOutOfBoundsException.class);
thrown.expectMessage("Index: 0, Size: 0");
new ArrayList<Object>().get(0);
}