Как вы утверждаете, что в тестах JUnit 4 выдается определенное исключение?
Как я могу использовать JUnit4 идиоматически, чтобы проверить, что некоторый код вызывает исключение?
Хотя я, конечно, могу сделать что-то вроде этого:
@Test
public void testFooThrowsIndexOutOfBoundsException() {
boolean thrown = false;
try {
foo.doStuff();
} catch (IndexOutOfBoundsException e) {
thrown = true;
}
assertTrue(thrown);
}
Я вспоминаю, что есть аннотация или Assert.xyz или что- то гораздо менее хитрое и гораздо более в духе JUnit для подобных ситуаций.
36 ответов
JUnit 4 поддерживает это:
@Test(expected = IndexOutOfBoundsException.class)
public void testIndexOutOfBoundsException() {
ArrayList emptyList = new ArrayList();
Object o = emptyList.get(0);
}
Редактировать Теперь, когда JUnit5 выпустила, лучшим вариантом будет использовать Assertions.assertThrows()
(см. мой другой ответ).
Если вы не мигрировали в JUnit 5, но можете использовать JUnit 4.7, вы можете использовать ExpectedException
Правило:
public class FooTest {
@Rule
public final ExpectedException exception = ExpectedException.none();
@Test
public void doStuffThrowsIndexOutOfBoundsException() {
Foo foo = new Foo();
exception.expect(IndexOutOfBoundsException.class);
foo.doStuff();
}
}
Это намного лучше чем @Test(expected=IndexOutOfBoundsException.class)
потому что тест не пройден, если IndexOutOfBoundsException
брошен раньше foo.doStuff()
Смотрите эту статью для деталей
Будьте осторожны, используя ожидаемое исключение, поскольку оно только утверждает, что метод вызвал это исключение, а не конкретную строку кода в тесте.
Я склонен использовать это для проверки параметров проверки, потому что такие методы, как правило, очень просты, но более сложные тесты лучше использовать:
try {
methodThatShouldThrow();
fail( "My method didn't throw when I expected it to" );
} catch (MyException expectedException) {
}
Примените суждение.
В junit есть четыре способа проверки исключения.
для junit4.x используйте необязательный атрибут "ожидается" аннотации Test
@Test(expected = IndexOutOfBoundsException.class) public void testFooThrowsIndexOutOfBoundsException() { foo.doStuff(); }
для junit4.x используйте правило ExpectedException
public class XxxTest { @Rule public ExpectedException thrown = ExpectedException.none(); @Test public void testFooThrowsIndexOutOfBoundsException() { thrown.expect(IndexOutOfBoundsException.class) //you can test the exception message like thrown.expectMessage("expected messages"); foo.doStuff(); } }
вы также можете использовать классический способ try/catch, широко используемый под инфраструктурой junit 3
@Test public void testFooThrowsIndexOutOfBoundsException() { try { foo.doStuff(); fail("expected exception was not occured."); } catch(IndexOutOfBoundsException e) { //if execution reaches here, //it indicates this exception was occured. //so we need not handle it. } }
наконец, для junit5.x вы также можете использовать assertThrows следующим образом
@Test public void testFooThrowsIndexOutOfBoundsException() { Throwable exception = assertThrows(IndexOutOfBoundsException.class, () -> foo.doStuff()); assertEquals("expected messages", exception.getMessage()); }
так
- 1-й способ используется, когда вы хотите проверить только тип исключения
- другие три способа используются, когда вы хотите проверить сообщение об исключении далее
- если вы используете junit 3, то третий предпочтительнее
- если тебе нравится junit 5, то тебе должен понравиться 4-й
Для получения дополнительной информации, вы можете прочитать этот документ и руководство пользователя junit5 для деталей.
Как уже говорилось ранее, в JUnit есть много способов справиться с исключениями. Но с Java 8 есть еще один: использование лямбда-выражений. С помощью лямбда-выражений мы можем получить такой синтаксис:
@Test
public void verifiesTypeAndMessage() {
assertThrown(new DummyService()::someMethod)
.isInstanceOf(RuntimeException.class)
.hasMessage("Runtime exception occurred")
.hasMessageStartingWith("Runtime")
.hasMessageEndingWith("occurred")
.hasMessageContaining("exception")
.hasNoCause();
}
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
Раскрытие информации: я являюсь автором блога и проекта.
ТЛ; др
pre-JDK8: я буду рекомендовать старый добрый
try
-catch
блок.post-JDK8: используйте AssertJ или пользовательские лямбды, чтобы утверждать исключительное поведение.
Независимо от Junit 4 или JUnit 5.
длинная история
Можно написать сам, сделай сам try
- catch
заблокировать или использовать инструменты JUnit (@Test(expected = ...)
или @Rule ExpectedException
JUnit правило особенность).
Но эти способы не так элегантны и не очень хорошо сочетаются с другими инструментами.
try
-catch
блок, вы должны написать блок вокруг тестируемого поведения и записать утверждение в блоке catch, что может быть хорошо, но многие находят, что этот стиль прерывает поток чтения теста. Также вам нужно написатьAssert.fail
в концеtry
блокировать в противном случае проверка может пропустить одну сторону утверждений; PMD, findbugs или Sonar обнаружат такие проблемы.@Test(expected = ...)
Эта функция интересна тем, что вы можете написать меньше кода, и тогда написание этого теста предположительно менее подвержено ошибкам кодирования. Но этому подходу не хватает некоторых областей.- Если тест должен проверить дополнительные вещи об исключении, такие как причина или сообщение (хорошие сообщения об исключениях действительно важны, точного типа исключения может быть недостаточно).
Кроме того, поскольку в методе заложено ожидание, в зависимости от того, как написан проверенный код, неправильная часть тестового кода может вызвать исключение, что приведет к ложному положительному тесту, и я не уверен, что PMD, findbugs или Sonar будут давать намеки на такой код.
@Test(expected = WantedException.class) public void call2_should_throw_a_WantedException__not_call1() { // init tested tested.call1(); // may throw a WantedException // call to be actually tested tested.call2(); // the call that is supposed to raise an exception }
ExpectedException
Правило также является попыткой исправить предыдущие предостережения, но его использование немного неудобно, так как в нем используется стиль ожидания, пользователи EasyMock хорошо знают этот стиль. Для некоторых это может быть удобно, но если вы следуете принципам Поведенческого развития (BDD) или Arrange Act Assert (AAA),ExpectedException
Правило не вписывается в стиль письма. Помимо этого он может страдать от той же проблемы, что и@Test
Кстати, в зависимости от того, где вы размещаете ожидание.@Rule ExpectedException thrown = ExpectedException.none() @Test public void call2_should_throw_a_WantedException__not_call1() { // expectations thrown.expect(WantedException.class); thrown.expectMessage("boom"); // init tested tested.call1(); // may throw a WantedException // call to be actually tested tested.call2(); // the call that is supposed to raise an exception }
Даже ожидаемое исключение помещается перед оператором теста, оно нарушает поток чтения, если тесты следуют BDD или AAA.
Также см. Этот вопрос комментария на JUnit автора
ExpectedException
,
Таким образом, эти вышеупомянутые опции имеют всю их нагрузку и явно не защищены от ошибок кодера.
Есть проект, о котором я узнал после создания этого ответа, который выглядит многообещающим, это ловушка-исключение.
Как говорится в описании проекта, он позволяет кодировщику писать беглую строку кода, перехватывающую исключение, и предлагает это исключение для последующего утверждения. И вы можете использовать любую библиотеку утверждений, такую как 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
), то, что может и не то, что вы хотите, так как у этого макетиста есть и другие недостатки, чем у обычного макетолога.Требуется еще одна тестовая зависимость.
Эти проблемы не будут применяться, если библиотека будет поддерживать лямбды, однако функциональность будет дублироваться набором инструментов 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
,
Я хотел бы сделать вывод, что сегодня (2017-03-03) простота использования AssertJ, обнаруживаемый API, быстрый темп разработки и фактическая зависимость от тестирования - это лучшее решение с JDK8 независимо от инфраструктуры тестирования (JUnit или нет), предыдущие JDK должны вместо этого полагаться на try
- catch
блоки, даже если они чувствуют себя неуклюже.
Этот ответ был скопирован с другого вопроса, который не имеет такой же видимости, я тот же автор.
Теперь, когда выпущен JUnit 5, лучше всего использовать Assertions.assertThrows()
(см. руководство пользователя Junit 5).
Вот пример, который проверяет, что исключение выдается, и использует Truth, чтобы сделать утверждения в сообщении об исключении:
public class FooTest {
@Test
public void doStuffThrowsIndexOutOfBoundsException() {
Foo foo = new Foo();
IndexOutOfBoundsException e = assertThrows(
IndexOutOfBoundsException.class, foo::doStuff);
assertThat(e).hasMessageThat().contains("woops!");
}
}
Преимущества над подходами в других ответах:
- Встроенный в Юнит
- Вы получаете полезное сообщение об исключении, если код в лямбде не генерирует исключение, и трассировку стека, если оно выдает другое исключение
- краткий
- Позволяет вашим тестам следовать Arrange-Act-Assert
- Вы можете точно указать, какой код вы ожидаете выбросить исключение
- Вам не нужно перечислять ожидаемое исключение в
throws
пункт - Вы можете использовать выбранную платформу утверждений, чтобы делать утверждения о перехваченном исключении
Аналогичный метод будет добавлен в org.junit Assert
в Юнит 4.13.
Обновление: JUnit5 имеет улучшение для тестирования исключений: assertThrows
,
Следующий пример из: Руководство пользователя Junit 5
@Test
void exceptionTesting() {
Throwable exception = assertThrows(IllegalArgumentException.class, () ->
{
throw new IllegalArgumentException("a message");
});
assertEquals("a message", exception.getMessage());
}
Оригинальный ответ с использованием JUnit 4.
Есть несколько способов проверить, что выбрасывается исключение. Я также обсудил следующие параметры в своем посте. Как писать отличные юнит-тесты с помощью JUnit.
Установить expected
параметр @Test(expected = FileNotFoundException.class)
,
@Test(expected = FileNotFoundException.class)
public void testReadFile() {
myClass.readFile("test.txt");
}
С помощью try
catch
public void testReadFile() {
try {
myClass.readFile("test.txt");
fail("Expected a FileNotFoundException to be thrown");
} catch (FileNotFoundException e) {
assertThat(e.getMessage(), is("The file test.txt does not exist!"));
}
}
Тестирование с ExpectedException
Правило.
@Rule
public ExpectedException thrown = ExpectedException.none();
@Test
public void testReadFile() throws FileNotFoundException {
thrown.expect(FileNotFoundException.class);
thrown.expectMessage(startsWith("The file test.txt"));
myClass.readFile("test.txt");
}
Вы можете прочитать больше о тестировании исключений в вики JUnit4 для тестирования исключений и bad.robot - Правило исключения JUnit для исключений.
Как насчет этого: поймайте очень общее исключение, убедитесь, что оно выбрано из блока catch, а затем подтвердите, что класс исключения соответствует ожидаемому. Это утверждение потерпит неудачу, если а) исключение будет неправильного типа (например, если вместо этого вы получили нулевой указатель) и б) исключение никогда не генерировалось.
public void testFooThrowsIndexOutOfBoundsException() {
Throwable e = null;
try {
foo.doStuff();
} catch (Throwable ex) {
e = ex;
}
assertTrue(e instanceof IndexOutOfBoundsException);
}
Используя утверждение AssertJ, которое можно использовать вместе с JUnit:
import static org.assertj.core.api.Assertions.*;
@Test
public void testFooThrowsIndexOutOfBoundsException() {
Foo foo = new Foo();
assertThatThrownBy(() -> foo.doStuff())
.isInstanceOf(IndexOutOfBoundsException.class);
}
Это лучше чем @Test(expected=IndexOutOfBoundsException.class)
потому что он гарантирует ожидаемую строку в тесте, вызвал исключение и позволяет вам проверить более подробную информацию об исключении, например сообщение, проще:
assertThatThrownBy(() ->
{
throw new Exception("boom!");
})
.isInstanceOf(Exception.class)
.hasMessageContaining("boom");
Решение в стиле BDD: JUnit 4 + Catch Exception + AssertJ
@Test
public void testFooThrowsIndexOutOfBoundsException() {
when(foo).doStuff();
then(caughtException()).isInstanceOf(IndexOutOfBoundsException.class);
}
Исходный код
зависимости
eu.codearte.catch-exception:catch-exception:1.3.3
Чтобы решить ту же проблему, я создал небольшой проект: http://code.google.com/p/catch-exception/
С помощью этого маленького помощника вы бы написали
verifyException(foo, IndexOutOfBoundsException.class).doStuff();
Это менее многословно, чем правило ExpectedException в JUnit 4.7. По сравнению с решением, предоставляемым skaffman, вы можете указать, в какой строке кода вы ожидаете исключения. Надеюсь, это поможет.
Вы также можете сделать это:
@Test
public void testFooThrowsIndexOutOfBoundsException() {
try {
foo.doStuff();
assert false;
} catch (IndexOutOfBoundsException e) {
assert true;
}
}
ИМХО, лучший способ проверить исключения в JUnit - это шаблон try/catch/fail/assert:
// this try block should be as small as possible,
// as you want to make sure you only catch exceptions from your code
try {
sut.doThing();
fail(); // fail if this does not throw any exception
} catch(MyException e) { // only catch the exception you expect,
// otherwise you may catch an exception for a dependency unexpectedly
// a strong assertion on the message,
// in case the exception comes from anywhere an unexpected line of code,
// especially important if your checking IllegalArgumentExceptions
assertEquals("the message I get", e.getMessage());
}
assertTrue
может быть немного сильным для некоторых людей, поэтому assertThat(e.getMessage(), containsString("the message");
может быть предпочтительнее.
Решение JUnit 5
@Test
void testFooThrowsIndexOutOfBoundsException() {
Throwable exception = expectThrows( IndexOutOfBoundsException.class, foo::doStuff );
assertEquals( "some message", exception.getMessage() );
}
Больше информации о JUnit 5 на http://junit.org/junit5/docs/current/user-guide/
Самый гибкий и элегантный ответ для Junit 4 я нашел в блоге Mkyong. Он обладает гибкостью try/catch
с использованием @Rule
аннотаций. Мне нравится этот подход, потому что вы можете прочитать определенные атрибуты настроенного исключения.
package com.mkyong;
import com.mkyong.examples.CustomerService;
import com.mkyong.examples.exception.NameNotFoundException;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.Matchers.hasProperty;
public class Exception3Test {
@Rule
public ExpectedException thrown = ExpectedException.none();
@Test
public void testNameNotFoundException() throws NameNotFoundException {
//test specific type of exception
thrown.expect(NameNotFoundException.class);
//test message
thrown.expectMessage(is("Name is empty!"));
//test detail
thrown.expect(hasProperty("errCode")); //make sure getters n setters are defined.
thrown.expect(hasProperty("errCode", is(666)));
CustomerService cust = new CustomerService();
cust.findByName("");
}
}
JUnit имеет встроенную поддержку для этого с "ожидаемым" атрибутом
Я попробовал многие из методов здесь, но они были либо сложными, либо не совсем отвечали моим требованиям. На самом деле, можно написать вспомогательный метод довольно просто:
public class ExceptionAssertions {
public static void assertException(BlastContainer blastContainer ) {
boolean caughtException = false;
try {
blastContainer.test();
} catch( Exception e ) {
caughtException = true;
}
if( !caughtException ) {
throw new AssertionFailedError("exception expected to be thrown, but was not");
}
}
public static interface BlastContainer {
public void test() throws Exception;
}
}
Используйте это так:
assertException(new BlastContainer() {
@Override
public void test() throws Exception {
doSomethingThatShouldExceptHere();
}
});
Нулевые зависимости: нет необходимости в mockito, нет необходимости в powermock; и отлично работает с выпускными классами.
Решение Java 8
Если вы хотите решение, которое:
- Использует лямбды Java 8
- Не зависит от какой-либо магии JUnit
- Позволяет проверить наличие нескольких исключений в одном методе тестирования.
- Проверяет исключение, генерируемое определенным набором строк в вашем методе тестирования вместо любой неизвестной строки во всем методе теста
- Возвращает действительный объект исключения, который был брошен, чтобы вы могли его дополнительно изучить
Вот полезная функция, которую я написал:
public final <T extends Throwable> T expectException( Class<T> exceptionClass, Runnable runnable )
{
try
{
runnable.run();
}
catch( Throwable throwable )
{
if( throwable instanceof AssertionError && throwable.getCause() != null )
throwable = throwable.getCause(); //allows "assert x != null : new IllegalArgumentException();"
assert exceptionClass.isInstance( throwable ) : throwable; //exception of the wrong kind was thrown.
assert throwable.getClass() == exceptionClass : throwable; //exception thrown was a subclass, but not the exact class, expected.
@SuppressWarnings( "unchecked" )
T result = (T)throwable;
return result;
}
assert false; //expected exception was not thrown.
return null; //to keep the compiler happy.
}
Используйте это следующим образом:
@Test
public void testThrows()
{
RuntimeException e = expectException( RuntimeException.class, () ->
{
throw new RuntimeException( "fail!" );
} );
assert e.getMessage().equals( "fail!" );
}
В моем случае я всегда получаю RuntimeException от db, но сообщения различаются. И исключение должно быть обработано соответственно. Вот как я это проверил:
@Test
public void testThrowsExceptionWhenWrongSku() {
// Given
String articleSimpleSku = "999-999";
int amountOfTransactions = 1;
Exception exception = null;
// When
try {
createNInboundTransactionsForSku(amountOfTransactions, articleSimpleSku);
} catch (RuntimeException e) {
exception = e;
}
// Then
shouldValidateThrowsExceptionWithMessage(exception, MESSAGE_NON_EXISTENT_SKU);
}
private void shouldValidateThrowsExceptionWithMessage(final Exception e, final String message) {
assertNotNull(e);
assertTrue(e.getMessage().contains(message));
}
Просто сделайте Matcher, который можно выключать и включать, вот так:
public class ExceptionMatcher extends BaseMatcher<Throwable> {
private boolean active = true;
private Class<? extends Throwable> throwable;
public ExceptionMatcher(Class<? extends Throwable> throwable) {
this.throwable = throwable;
}
public void on() {
this.active = true;
}
public void off() {
this.active = false;
}
@Override
public boolean matches(Object object) {
return active && throwable.isAssignableFrom(object.getClass());
}
@Override
public void describeTo(Description description) {
description.appendText("not the covered exception type");
}
}
Чтобы использовать это:
добавлять public ExpectedException exception = ExpectedException.none();
, затем:
ExceptionMatcher exMatch = new ExceptionMatcher(MyException.class);
exception.expect(exMatch);
someObject.somethingThatThrowsMyException();
exMatch.off();
В JUnit 4 или более поздней версии вы можете проверить исключения следующим образом
@Rule
public ExpectedException exceptions = ExpectedException.none();
это предоставляет множество функций, которые можно использовать для улучшения наших тестов JUnit.
Если вы видите приведенный ниже пример, я тестирую 3 вещи на исключение.
- Тип создаваемого исключения
- Сообщение об исключении
- Причина исключения
public class MyTest {
@Rule
public ExpectedException exceptions = ExpectedException.none();
ClassUnderTest classUnderTest;
@Before
public void setUp() throws Exception {
classUnderTest = new ClassUnderTest();
}
@Test
public void testAppleisSweetAndRed() throws Exception {
exceptions.expect(Exception.class);
exceptions.expectMessage("this is the exception message");
exceptions.expectCause(Matchers.<Throwable>equalTo(exceptionCause));
classUnderTest.methodUnderTest("param1", "param2");
}
}
Мы можем использовать утверждение сбоя после метода, который должен вернуть исключение:
try{
methodThatThrowMyException();
Assert.fail("MyException is not thrown !");
} catch (final Exception exception) {
// Verify if the thrown exception is instance of MyException, otherwise throws an assert failure
assertTrue(exception instanceof MyException, "An exception other than MyException is thrown !");
// In case of verifying the error message
MyException myException = (MyException) exception;
assertEquals("EXPECTED ERROR MESSAGE", myException.getMessage());
}
В дополнение к тому, что сказал NamshubWriter, убедитесь, что:
- Экземпляр ExpectedException является открытым ( связанный вопрос)
- ExpectedException не создается, например, в методе @Before. Этот пост ясно объясняет все тонкости порядка исполнения JUnit.
Не делай этого:
@Rule
public ExpectedException expectedException;
@Before
public void setup()
{
expectedException = ExpectedException.none();
}
Наконец, этот блог ясно иллюстрирует, как утверждать, что выбрасывается определенное исключение.
Я рекомендую библиотеку assertj-core
обработать исключение в тесте junit
В Java 8, как это:
//given
//when
Throwable throwable = catchThrowable(() -> anyService.anyMethod(object));
//then
AnyException anyException = (AnyException) throwable;
assertThat(anyException.getMessage()).isEqualTo("........");
assertThat(exception.getCode()).isEqualTo(".......);
Решение Junit4 с Java8 заключается в использовании этой функции:
public Throwable assertThrows(Class<? extends Throwable> expectedException, java.util.concurrent.Callable<?> funky) {
try {
funky.call();
} catch (Throwable e) {
if (expectedException.isInstance(e)) {
return e;
}
throw new AssertionError(
String.format("Expected [%s] to be thrown, but was [%s]", expectedException, e));
}
throw new AssertionError(
String.format("Expected [%s] to be thrown, but nothing was thrown.", expectedException));
}
Использование тогда:
assertThrows(ValidationException.class,
() -> finalObject.checkSomething(null));
Обратите внимание, что единственным ограничением является использование final
ссылка на объект в лямбда-выражении. Это решение позволяет продолжить тестовые утверждения вместо ожидаемых значений на уровне метода, используя @Test(expected = IndexOutOfBoundsException.class)
решение.
В JUnit framework есть assertThrows()
метод:
ArithmeticException exception = assertThrows(ArithmeticException.class, () ->
calculator.divide(1, 0));
assertEquals("/ by zero", exception.getMessage());
- для JUnit 5 это в
org.junit.jupiter.api.Assertions
класс; - для JUnit 4.13 это в
org.junit.Assert
класс; - для более ранних версий JUnit 4: просто добавьте ссылку на
org.junit.jupiter:junit-jupiter-api
в свой проект, и вы получите отлично работающую версию от JUnit 5.
я хотел бы использоватьassertThatThrownBy
@Test
public void testFooThrowsIndexOutOfBoundsException() {
assertThatThrownBy(() -> doStuff()).isInstanceOf(IndexOutOfBoundsException.class)
}
Взять, к примеру, вы хотите написать Junit для указанного ниже фрагмента кода.
public int divideByZeroDemo(int a,int b){
return a/b;
}
public void exceptionWithMessage(String [] arr){
throw new ArrayIndexOutOfBoundsException("Array is out of bound");
}
Приведенный выше код предназначен для проверки некоторых неизвестных исключений, которые могут возникнуть, а следующий - для подтверждения некоторых исключений с помощью настраиваемого сообщения.
@Rule
public ExpectedException exception=ExpectedException.none();
private Demo demo;
@Before
public void setup(){
demo=new Demo();
}
@Test(expected=ArithmeticException.class)
public void testIfItThrowsAnyException() {
demo.divideByZeroDemo(5, 0);
}
@Test
public void testExceptionWithMessage(){
exception.expectMessage("Array is out of bound");
exception.expect(ArrayIndexOutOfBoundsException.class);
demo.exceptionWithMessage(new String[]{"This","is","a","demo"});
}
@Test(expectedException=IndexOutOfBoundsException.class)
public void testFooThrowsIndexOutOfBoundsException() throws Exception {
doThrow(IndexOutOfBoundsException.class).when(foo).doStuff();
try {
foo.doStuff();
} catch (IndexOutOfBoundsException e) {
assertEquals(IndexOutOfBoundsException .class, ex.getCause().getClass());
throw e;
}
}
Вот еще один способ проверить, правильно ли выброшено исключение или нет.