среда, 1 августа 2012 г.

testing: junit - exeptions testing

Проверить что код ведет себя корректно в штатных ситуациях важно. Но также важно проверить, что он ведет себя корректно и в нештатных ситуациях. Рассмотрим код
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);
}