Есть проект, о котором я узнал после создания этого ответа, который выглядит многообещающим, это ловушка-исключение .
Как говорится в описании проекта, он позволяет кодировщику писать в беглой строке кода, перехватывающей исключение, и предлагает это исключение для последнего утверждения. И вы можете использовать любую библиотеку утверждений, такую как Hamcrest или AssertJ .
Быстрый пример взят с домашней страницы:
// given: an empty list
List myList = new ArrayList();
// when: we try to get the first element of the list
when(myList).get(1);
// then: we expect an IndexOutOfBoundsException
then(caughtException())
.isInstanceOf(IndexOutOfBoundsException.class)
.hasMessage("Index: 1, Size: 0")
.hasNoCause();
Как видите, код действительно прост, вы ловите исключение в определенной строке, then
API - это псевдоним, который будет использовать API-интерфейсы AssertJ (аналогично использованию assertThat(ex).hasNoCause()...
). В какой-то момент проект опирался на FEST-Assert, предка AssertJ . РЕДАКТИРОВАТЬ: Кажется, что проект готовит поддержку Java 8 Lambdas.
В настоящее время эта библиотека имеет два недостатка:
На момент написания этой статьи стоит отметить, что эта библиотека основана на Mockito 1.x, поскольку она создает макет тестируемого объекта за сценой. Поскольку Mockito все еще не обновлен, эта библиотека не может работать с финальными классами или финальными методами . И даже если бы он был основан на Mockito 2 в текущей версии, для этого потребовалось бы объявить глобального создателя макетов (inline-mock-maker
), что может не соответствовать вашему желанию, так как этот mock maker имеет другие недостатки, чем обычный mock maker.
Требуется еще одна тестовая зависимость.
Эти проблемы не будут применяться, если библиотека поддерживает лямбды. Однако функциональность будет дублироваться набором инструментов AssertJ.
Принимая все во внимание, если вы не хотите использовать инструмент catch-exception, я порекомендую старый добрый способ try
- catch
блока, по крайней мере, до JDK7. А для пользователей JDK 8 вы можете предпочесть использовать AssertJ, поскольку он предлагает больше, чем просто утверждение исключений.
С JDK8 лямбды выходят на тестовую сцену, и они оказались интересным способом заявить об исключительном поведении. AssertJ был обновлен, чтобы обеспечить хороший свободный API для утверждения исключительного поведения.
И пример теста с AssertJ :
@Test
public void test_exception_approach_1() {
...
assertThatExceptionOfType(IOException.class)
.isThrownBy(() -> someBadIOOperation())
.withMessage("boom!");
}
@Test
public void test_exception_approach_2() {
...
assertThatThrownBy(() -> someBadIOOperation())
.isInstanceOf(Exception.class)
.hasMessageContaining("boom");
}
@Test
public void test_exception_approach_3() {
...
// when
Throwable thrown = catchThrowable(() -> someBadIOOperation());
// then
assertThat(thrown).isInstanceOf(Exception.class)
.hasMessageContaining("boom");
}
С почти полным переписыванием JUnit 5 утверждения были немного улучшены , они могут оказаться интересными как готовый способ утверждать должным образом исключение. Но на самом деле API утверждений все еще немного плох, снаружи ничего нет assertThrows
.
@Test
@DisplayName("throws EmptyStackException when peeked")
void throwsExceptionWhenPeeked() {
Throwable t = assertThrows(EmptyStackException.class, () -> stack.peek());
Assertions.assertEquals("...", t.getMessage());
}
Как вы заметили assertEquals
он все еще возвращается void
и поэтому не позволяет создавать цепочки утверждений вроде AssertJ.
Также, если вы помните, что имя конфликтует с Matcher
или Assert
, будьте готовы встретить то же самое столкновение с Assertions
.
org.mockito.Mockito.verify
с различными параметрами, чтобы убедиться, что определенные вещи произошли (например, служба логгера была вызвана с правильными параметрами) до того, как возникло исключение.