Как я могу использовать JUnit4 идиоматически, чтобы проверить, что некоторый код вызывает исключение?
Хотя я, конечно, могу сделать что-то вроде этого:
@Test
public void testFooThrowsIndexOutOfBoundsException() {
boolean thrown = false;
try {
foo.doStuff();
} catch (IndexOutOfBoundsException e) {
thrown = true;
}
assertTrue(thrown);
}
Я вспоминаю, что есть аннотация или Assert.xyz или что- то гораздо менее хитрое и гораздо более в духе JUnit для подобных ситуаций.
org.mockito.Mockito.verify
с различными параметрами, чтобы убедиться, что определенные вещи произошли (например, служба логгера была вызвана с правильными параметрами) до того, как возникло исключение.Ответы:
Это зависит от версии JUnit и от того, какие библиотеки утверждений вы используете.
Оригинальный ответ
JUnit <= 4.12
был:Хотя ответ https://stackoverflow.com/a/31826781/2986984 имеет больше возможностей для JUnit <= 4.12.
Ссылка :
источник
ArrayList
отвечает, неget()
имеет значения. Если бы я решил в будущем перейти к примитивному массиву, мне пришлось бы изменить эту тестовую реализацию. Структура данных должна быть скрыта, чтобы тест мог сосредоточиться на поведении класса .Изменить: Теперь, когда JUnit 5 и JUnit 4.13 были выпущены, лучший вариант будет использовать
Assertions.assertThrows()
(для JUnit 5) иAssert.assertThrows()
(для JUnit 4.13). Смотрите мой другой ответ для деталей.Если вы не мигрировали в JUnit 5, но можете использовать JUnit 4.7, вы можете использовать
ExpectedException
правило:Это гораздо лучше, чем
@Test(expected=IndexOutOfBoundsException.class)
потому, что тест не пройдёт, еслиIndexOutOfBoundsException
его бросить раньшеfoo.doStuff()
Смотрите эту статью для деталей
источник
ExpectedException
класса есть способы сопоставления сообщения об исключении или даже написания собственного сопоставителя, который зависит от класса исключения. Во-вторых, вы можете установить свое ожидание непосредственно перед строкой кода, в которой вы ожидаете выбросить исключение - это означает, что ваш тест не пройдёт, если неправильная строка кода выдаст исключение; в то время как нет способа сделать это с помощью решения Скаффмана.Будьте осторожны, используя ожидаемое исключение, поскольку оно только утверждает, что метод вызвал это исключение, а не конкретную строку кода в тесте.
Я склонен использовать это для проверки параметров проверки, потому что такие методы, как правило, очень просты, но более сложные тесты лучше использовать:
Примените суждение.
источник
ExpectedException
обычно нужно установить ожидание непосредственно перед строкой, которую вы ожидаете выбросить. Таким образом, если более ранняя строка выдает исключение, оно не сработает, и тест завершится неудачей.Как уже говорилось ранее, в JUnit есть много способов обработки исключений. Но с Java 8 есть еще один: использование лямбда-выражений. С помощью лямбда-выражений мы можем получить такой синтаксис:
assertThrown принимает функциональный интерфейс, экземпляры которого можно создавать с помощью лямбда-выражений, ссылок на методы или ссылок на конструкторы. assertThrown, принимающий этот интерфейс, будет ожидать и быть готовым обработать исключение.
Это относительно простая, но мощная техника.
Посмотрите на этот пост в блоге, описывающий эту технику: http://blog.codeleak.pl/2014/07/junit-testing-exception-with-java-8-and-lambda-expressions.html
Исходный код можно найти здесь: https://github.com/kolorobot/unit-testing-demo/tree/master/src/test/java/com/github/kolorobot/exceptions/java8
Раскрытие: я являюсь автором блога и проекта.
источник
new DummyService()::someMethod
естьMethodHandle
, но этот подход одинаково хорошо работает с лямбда-выражениями.в junit есть четыре способа проверки исключения.
junit5.x
для junit5.x вы можете использовать
assertThrows
следующееjunit4.x
для junit4.x используйте необязательный атрибут «ожидается» аннотации теста
для junit4.x используйте правило ExpectedException
вы также можете использовать классический способ try / catch, широко используемый под инфраструктурой junit 3
так
для получения дополнительной информации, вы можете прочитать этот документ и руководство пользователя junit5 для деталей.
источник
Trowable
методаExpectedException.expect
. посмотри пожалуйста это подпись . @miuserТЛ; др
post-JDK8: используйте AssertJ или пользовательские лямбды, чтобы утверждать исключительное поведение.
предварительно JDK8: Я буду рекомендовать хороший старый
try
-catch
блок. ( Не забудьте добавитьfail()
утверждение передcatch
блоком )Независимо от Junit 4 или JUnit 5.
длинная история
Можно написать себе сделать это самостоятельно
try
-catch
заблокировать или использовать инструменты JUnit (@Test(expected = ...)
или@Rule ExpectedException
функцию правила JUnit).Но эти способы не так элегантно и не хорошо перемешать читаемость мудрого с другими инструментами. Более того, инструменты JUnit имеют некоторые подводные камни.
Блок
try
-catch
вы должны написать блок вокруг тестируемого поведения и записать утверждение в блоке catch, что может быть хорошо, но многие считают, что этот стиль прерывает поток чтения теста. Кроме того, вам нужно написатьAssert.fail
в концеtry
блока. В противном случае проверка может пропустить одну сторону утверждений; PMD , findbugs или Sonar определят такие проблемы.@Test(expected = ...)
функция интересна тем, что вы можете написать меньше кода, а затем этот тест, предположительно, менее подвержен ошибкам кодирования. Но этот подход отсутствует в некоторых областях.Кроме того, поскольку в методе заложено ожидание, в зависимости от того, как написан проверенный код, неправильная часть тестового кода может вызвать исключение, приводящее к ложноположительному тесту, и я не уверен, что PMD , findbugs или Sonar даст подсказки по такому коду.
Это
ExpectedException
правило также является попыткой исправить предыдущие предостережения, но его использование немного неудобно, так как в нем используется стиль ожидания, пользователи EasyMock очень хорошо знают этот стиль. Для некоторых это может быть удобно, но если вы следуете принципам Поведенческого развития (BDD) или Arrange Act Assert (AAA),ExpectedException
правило не будет соответствовать этому стилю написания. Помимо этого он может страдать от той же проблемы, что и@Test
путь, в зависимости от того, где вы ожидаете.Даже ожидаемое исключение помещается перед оператором теста, оно нарушает поток чтения, если тесты следуют BDD или AAA.
Также смотрите этот комментарий к вопросу о JUnit автора
ExpectedException
. JUnit 4.13-beta-2 даже не поддерживает этот механизм:Таким образом, эти вышеупомянутые опции имеют всю их нагрузку и явно не защищены от ошибок кодера.
Есть проект, о котором я узнал после создания этого ответа, который выглядит многообещающим, это ловушка-исключение .
Как говорится в описании проекта, он позволяет кодировщику писать в беглой строке кода, перехватывающей исключение, и предлагает это исключение для последнего утверждения. И вы можете использовать любую библиотеку утверждений, такую как Hamcrest или AssertJ .
Быстрый пример взят с домашней страницы:
Как видите, код действительно прост, вы ловите исключение в определенной строке,
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 :
С почти полным переписыванием JUnit 5 утверждения были немного улучшены , они могут оказаться интересными как готовый способ утверждать должным образом исключение. Но на самом деле API утверждений все еще немного плох, снаружи ничего нет
assertThrows
.Как вы заметили
assertEquals
он все еще возвращаетсяvoid
и поэтому не позволяет создавать цепочки утверждений вроде AssertJ.Также, если вы помните, что имя конфликтует с
Matcher
илиAssert
, будьте готовы встретить то же самое столкновение сAssertions
.Я хотел бы сделать вывод, что сегодня (2017-03-03) простота использования AssertJ , обнаруживаемый API, быстрый темп разработки и фактическая зависимость от тестирования - лучшее решение с JDK8 независимо от среды тестирования (JUnit или нет) ранее JDKs вместо этого следует полагаться на
try
-catch
блоков , даже если они чувствуют себя неуклюжими.Этот ответ был скопирован с другого вопроса, который не имеет такой же видимости, я тот же автор.
источник
Теперь, когда JUnit 5 и JUnit 4.13 были выпущены, лучшим вариантом будет использование
Assertions.assertThrows()
(для JUnit 5) иAssert.assertThrows()
(для JUnit 4.13). Смотрите руководство пользователя Junit 5 .Вот пример, который проверяет, что исключение выдается, и использует Truth, чтобы сделать утверждения в сообщении об исключении:
Преимущества над подходами в других ответах:
throws
предложенииАналогичный метод будет добавлен
org.junit Assert
в JUnit 4.13.источник
Как насчет этого: поймайте очень общее исключение, убедитесь, что оно выбрано из блока catch, а затем подтвердите, что класс исключения соответствует ожидаемому. Это утверждение потерпит неудачу, если а) исключение будет неправильного типа (например, если вместо этого вы получили нулевой указатель) и б) исключение никогда не генерировалось.
источник
assertEquals(ExpectedException.class, e.getClass())
покажет вам ожидаемые и фактические значения, когда тест не пройден.Решение в стиле BDD : JUnit 4 + Catch Exception + AssertJ
зависимости
источник
Используя утверждение AssertJ , которое можно использовать вместе с JUnit:
Это лучше, чем
@Test(expected=IndexOutOfBoundsException.class)
потому, что он гарантирует, что ожидаемая строка в тесте вызвала исключение, и позволяет вам проверить более подробную информацию об исключении, например, сообщение:Инструкции Maven / Gradle здесь.
источник
assertThat
, всегда AssertJ. Кроме того, метод JUnit возвращает только «обычный» тип, тогда как метод AssertJ возвращаетAbstractAssert
подкласс ..., позволяющий структурировать методы, как указано выше (или любые другие технические термины для этого ...).Чтобы решить ту же проблему, я создал небольшой проект: http://code.google.com/p/catch-exception/
С помощью этого маленького помощника вы бы написали
Это менее многословно, чем правило ExpectedException в JUnit 4.7. По сравнению с решением, предоставляемым skaffman, вы можете указать, в какой строке кода вы ожидаете исключения. Надеюсь, это поможет.
источник
foo
этоfinal
будет не потому , что вы не можете проксиfoo
?Обновление: JUnit5 имеет улучшение для тестирования исключений:
assertThrows
.Следующий пример взят из: Руководство пользователя Junit 5
Оригинальный ответ с использованием JUnit 4.
Есть несколько способов проверить, что выбрасывается исключение. Я также обсудил ниже варианты в моем посте Как написать отличные юнит-тесты с JUnit
Установите
expected
параметр@Test(expected = FileNotFoundException.class)
.С помощью
try
catch
Тестирование с
ExpectedException
правилом.Вы можете прочитать больше о тестировании исключений в вики JUnit4 для тестирования исключений и bad.robot - Правило исключения JUnit Expecting .
источник
Вы также можете сделать это:
источник
Assert.fail()
, а неassert
на тот случай, если ваши тесты выполняются в среде, где утверждения не включены.ИМХО, лучший способ проверить наличие исключений в JUnit - это шаблон try / catch / fail / assert:
Это
assertTrue
может быть немного сильным для некоторых людей, поэтомуassertThat(e.getMessage(), containsString("the message");
может быть предпочтительнее.источник
Решение JUnit 5
Больше информации о JUnit 5 на http://junit.org/junit5/docs/current/user-guide/#writing-tests-assertions
источник
expectThrows()
является частью TestNG, а не JUnitСамый гибкий и элегантный ответ для Junit 4 я нашел в блоге Mkyong . Он имеет гибкость
try/catch
использования@Rule
аннотации. Мне нравится этот подход, потому что вы можете прочитать определенные атрибуты настроенного исключения.источник
Я попробовал многие методы здесь, но они были либо сложными, либо не совсем отвечали моим требованиям. На самом деле, можно написать вспомогательный метод довольно просто:
Используйте это так:
Нулевые зависимости: нет необходимости в mockito, нет необходимости в powermock; и отлично работает с выпускными классами.
источник
Java 8 решение
Если вы хотите решение, которое:
Вот полезная функция, которую я написал:
( взято из моего блога )
Используйте это следующим образом:
источник
JUnit имеет встроенную поддержку для этого с атрибутом «ожидаемый»
источник
В моем случае я всегда получаю RuntimeException от db, но сообщения различаются. И исключение должно быть обработано соответственно. Вот как я это проверил:
источник
} catch (
, вы должны вставитьfail("no exception thrown");
Просто создайте Matcher, который можно выключать и включать, вот так:
Чтобы использовать это:
public ExpectedException exception = ExpectedException.none();
затем добавьте :источник
В JUnit 4 или более поздней версии вы можете проверить исключения следующим образом
это обеспечивает множество функций, которые можно использовать для улучшения наших тестов JUnit.
Если вы видите приведенный ниже пример, я тестирую 3 вещи на исключение.
источник
Мы можем использовать утверждение сбоя после метода, который должен вернуть исключение:
источник
catch
будет проглотить трассировку стека, если возникнет какое-то другое исключение, потеряв полезную информациюВ дополнение к тому, что сказал NamShubWriter , убедитесь, что:
Вы не делать этого:
Наконец, этот блог ясно иллюстрирует, как утверждать, что выбрасывается определенное исключение.
источник
Я рекомендую библиотеку
assertj-core
для обработки исключений в тесте junitВ Java 8, как это:
источник
Решение Junit4 с Java8 заключается в использовании этой функции:
Использование тогда:
Обратите внимание, что единственным ограничением является использование
final
ссылки на объект в лямбда-выражении. Это решение позволяет продолжить тестовые утверждения вместо ожидаемых результатов на уровне метода с использованием@Test(expected = IndexOutOfBoundsException.class)
решения.источник
Взять, к примеру, вы хотите написать Junit для указанного ниже фрагмента кода.
Приведенный выше код предназначен для проверки некоторых неизвестных исключений, которые могут возникнуть, а приведенный ниже - для подтверждения некоторых исключений с помощью настраиваемого сообщения.
источник
Вот еще один способ проверить, правильно ли выброшено исключение или нет.
источник
JUnit Framework имеет
assertThrows()
метод:org.junit.jupiter.api.Assertions
классе;org.junit.Assert
классе;org.junit.jupiter:junit-jupiter-api
свой проект, и вы получите отлично работающую версию от JUnit 5.источник
В Java 8 вы можете создать метод, принимающий код для проверки и ожидаемое исключение в качестве параметров:
а затем внутри вашего теста:
Льготы:
источник