How do you verify that code throws exceptions as expected?
Verifying that code completes normally is important, but making sure the code behaves as expected in exceptional situations is vital too. For example:
new ArrayList<Object>().get(0);
This code should throw an IndexOutOfBoundsException. There are multiple ways in JUnit to write a test to verify this behavior.
Using assertThrows
Method
The method assertThrows
has been added to the Assert
class in version 4.13. With this method you can assert that a given function call (specified, for instance, as a lambda expression or method reference) results in a particular type of exception being thrown. In addition it returns the exception that was thrown, so that further assertions can be made (e.g. to verify that the message and cause are correct). Furthermore, you can make assertions on the state of a domain object after the exception has been thrown:
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertThrows; import static org.junit.Assert.assertTrue; import java.util.ArrayList; import java.util.List; import org.junit.Test; @Test public void testExceptionAndState() { List<Object> list = new ArrayList<>(); IndexOutOfBoundsException thrown = assertThrows( IndexOutOfBoundsException.class, () -> list.add(1, new Object())); // assertions on the thrown exception assertEquals("Index: 1, Size: 0", thrown.getMessage()); // assertions on the state of a domain object after the exception has been thrown assertTrue(list.isEmpty()); }
Try/Catch Idiom
If you project is not yet using JUnit 4.13 or your code base does not support lambdas, you can use the try/catch idiom which prevailed in JUnit 3.x:
@Test public void testExceptionMessage() { List<Object> list = new ArrayList<>(); try { list.get(0); fail("Expected an IndexOutOfBoundsException to be thrown"); } catch (IndexOutOfBoundsException anIndexOutOfBoundsException) { assertThat(anIndexOutOfBoundsException.getMessage(), is("Index: 0, Size: 0")); } }
Be aware that fail()
throws an AssertionError
, so you cannot use the above idiom to verify that a method call should throw an AssertionError
.
Specifying the expected annotation via the @Test
annotation.
The @Test
annotation has an optional parameter «expected
» that takes as values subclasses of Throwable
. If we wanted to verify that ArrayList
throws the correct exception, we could write:
@Test(expected = IndexOutOfBoundsException.class) public void empty() { new ArrayList<Object>().get(0); }
The expected
parameter should be used with care. The above test will pass if any code in the method throws IndexOutOfBoundsException
. Using the method you also cannot test the value of the message in the exception, or the state of a domain object after the exception has been thrown.
For these reasons, the previous approaches are recommended.
ExpectedException Rule
Another way to test exceptions is the ExpectedException
rule, but that approach has been deprecated in JUnit 4.13. This rule let you indicate not only what exception you are expecting, but also the exception message you are expecting:
@Rule public ExpectedException thrown = ExpectedException.none(); @Test public void shouldTestExceptionMessage() throws IndexOutOfBoundsException { List<Object> list = new ArrayList<Object>(); thrown.expect(IndexOutOfBoundsException.class); thrown.expectMessage("Index: 0, Size: 0"); list.get(0); // execution will never get past this line }
The expectMessage also lets you use Matchers, which gives you a bit more flexibility in your tests. An example:
thrown.expectMessage(CoreMatchers.containsString("Size: 0"));
Moreover, you can use Matchers to inspect the Exception, useful if it has embedded state you wish to verify. For example
import static org.hamcrest.Matchers.hasProperty; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.startsWith; import javax.ws.rs.NotFoundException; import javax.ws.rs.core.Response; import javax.ws.rs.core.Response.Status; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; public class TestExy { @Rule public ExpectedException thrown = ExpectedException.none(); @Test public void shouldThrow() { TestThing testThing = new TestThing(); thrown.expect(NotFoundException.class); thrown.expectMessage(startsWith("some Message")); thrown.expect(hasProperty("response", hasProperty("status", is(404)))); testThing.chuck(); } private class TestThing { public void chuck() { Response response = Response.status(Status.NOT_FOUND).entity("Resource not found").build(); throw new NotFoundException("some Message", response); } } }
For an expanded discussion of the ExpectedException
rule, see this blog post.
Do note that when the test calls the method under test that throws the exception, no code in the test after the method will execute (because the method under test is throwing the exception). This can lead to confusion, which is one of the reasons why ExpectedException.none()
is deprecated.
Время прочтения
3 мин
Просмотры 11K
Это продолжение туториала по JUnit 5. Введение опубликовано здесь.
В JUnit 5, чтобы написать тестовый код, который, как ожидается, вызовет исключение, мы должны использовать Assertions.assertThrows().
В данном примере ожидается, что тестовый код в комментированном блоке вызовет исключение типа ApplicationException
.
Использование Assertions.assertThrows()
@Test
void testExpectedException() {
ApplicationException thrown = Assertions.assertThrows(ApplicationException.class, () -> {
//Code under test
});
Assertions.assertEquals("some message", exception.getMessage());
}
Оглавление
-
Assertions API assertThrows ().
-
Синтаксис
-
Вывод теста
-
-
Ожидаемое исключение генерируется в тесте.
-
Сгенерировано исключение другого типа, или не сгенерировано исключение
1. Assertions API assertThrows ()
1.1. Синтаксис
Метод assertThrows()
утверждает, что выполнение прилагаемого исполняемого блока или лямбда — выражения вызывает исключение типа expectedType
. Это перегруженный метод, который принимает следующие параметры.
static <T extends Throwable>T assertThrows(Class<T> expectedType, Executable executable)
static <T extends Throwable>T assertThrows(Class<T> expectedType, Executable executable, String message)
static <T extends Throwable>T assertThrows(Class<T> expectedType, Executable executable, Supplier<String> messageSupplier)
-
expectedType
— ожидается, что тестовый код вызовет исключение этого типа. -
message
— если исполняемый код не вызывает никаких исключений, это сообщение будет напечатано вместе с результатом FAIL. -
messageSupplier
— сообщение будет извлечено из него в случае неудачи теста.
1.2. Вывод теста
Если в блоке не было генерировано исключение, executable
, то assertThrows()
вернет FAIL
.
Если выбрасывается исключение другого типа, assertThrows()
будет FAIL
.
Если блок кода вызывает исключение класса, который является подтипом исключения expectedType
, только тогда assertThrows()
вернет PASS
.
Например, если мы ожидаем, IllegalArgumentException
и тест выдает ошибку NumberFormatException,
тогда и вывод теста будет PASS
потому что NumberFormatException расширяет класс IllegalArgumentException.
Кроме того, если мы передадим Exception.class
в качестве ожидаемого типа исключения, любое исключение, выброшенное из исполняемого блока, сделает результат assertion равным PASS
, поскольку Exception
является супертипом для всех исключений.
2. Ожидаемое исключение генерируемое в тесте
Ниже приведен очень простой тест, который ожидает, что исключение NumberFormatException
будет сгенерировано при выполнении предоставленного блока кода.
Оба теста выдают PASS
@Test
void testExpectedException() {
NumberFormatException thrown = Assertions.assertThrows(NumberFormatException.class, () -> {
Integer.parseInt("One");
}, "NumberFormatException was expected");
Assertions.assertEquals("For input string: "One"", thrown.getMessage());
}
@Test
void testExpectedExceptionWithParentType() {
Assertions.assertThrows(IllegalArgumentException.class, () -> {
Integer.parseInt("One");
});
}
-
В тесте
testExpectedException
, исполняемый кодInteger.parseInt("One")
генерирует исключениеNumberFormatException,
если аргумент метода не является допустимым текстовым представлением числа. МетодassertThrows()
ожидает это исключение, так что результат тестаPASS
. -
В тесте
testExpectedExceptionWithParentType
, мы выполняем тот же код, но на этот раз мы принимаем исключениеIllegalArgumentException
, родительское дляNumberFormatException
. Этот тест тоже проходит.
3. Сгенерировано исключение другого типа, или не сгенерировано исключение
Если исполняемый код вызывает исключение любого другого типа, то результат теста будет FAIL
.
И даже если исполняемый код не вызывает никаких исключений, результат теста тоже будет FAIL
.
Например, в приведенном ниже примере "1"
это допустимое число, поэтому исключение не возникает. Этот тест завершится ошибкой с сообщением в консоли.
@Test
void testExpectedExceptionFail() {
NumberFormatException thrown = Assertions
.assertThrows(NumberFormatException.class, () -> {
Integer.parseInt("1");
}, "NumberFormatException error was expected");
Assertions.assertEquals("Some expected message", thrown.getMessage());
}
В этом посте мы узнали, как написать тест, ожидающий возникновение исключений. Эти тесты полезны при тестировании кода, написанного в блоках catch.
Хорошего изучения!!!
Скачать исходный код
This post explores some techniques for asserting exceptions in Java with JUnit.
Table of contents
- Using
try
—catch
withfail()
- Using
@Test
withexpected
- Using
@Rule
withExpectedException
- Using
assertThrows
from JUnit 5 - Using AssertJ
- Bottom line and my thoughts
Using try
—catch
with fail()
In this approach, the code which is excepted to throw an exception is wrapped in a try
—catch
block.
Then the fail()
method is called immediately after the code that should throw the exception, so that if the exception is not thrown, the test fails. Then assertions can be performed on the exception that has been caught:
import org.junit.Test;
import static org.hamcrest.CoreMatchers.instanceOf;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.fail;
public class UsingTryCatchWithFail {
private Foo foo = new Foo();
@Test
public void doStuff_shouldThrowException() {
try {
// This method is expected to throw a FooException
foo.doStuff();
// If the exception is not thrown, the test will fail
fail("Expected exception has not been thrown");
} catch (FooException e) {
assertThat(e.getMessage(), is("An exception has occurred"));
assertThat(e.getCause(), instanceOf(IllegalStateException.class));
}
}
}
Using @Test
with expected
In this approach, the @Test
annotation is used to indicate the expected
exception to be thrown in the test:
import org.junit.Test;
public class UsingTestWithExpected {
private Foo foo = new Foo();
@Test(expected = FooException.class)
public void doStuff_shouldThrowException() {
foo.doStuff();
}
}
While it’s a simple approach, it lacks the ability of asserting both the message and the cause of the exception that has been thrown. As good exception messages are valuable, assertions on messages should be taken into account.
Also, depending on how the test is written, this approach should be discouraged: As the exception expectation is placed around the whole test method, this might not actually test what is itended to be tested, leading to false positives results, as shown below:
@Test(expected = FooException.class)
public void prepareToDoStuff_shouldSucceed_doStuff_shouldThrowException() {
// This method may throw a FooException, which may lead to a false positive result
foo.prepareToDoStuff();
// This is the method that is supposed to throw the actual FooException being asserted
foo.doStuff();
}
Using @Rule
with ExpectedException
This approach uses the ExpectedException
rule to assert an exception and also gives the ability of making assertions on both the message and the cause of the exeption:
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import static org.hamcrest.core.IsInstanceOf.instanceOf;
public class UsingRuleWithExpectedException {
private Foo foo = new Foo();
@Rule
public final ExpectedException thrown = ExpectedException.none();
@Test
public void doStuff_shouldThrowException() {
thrown.expect(FooException.class);
thrown.expectMessage("An exception has occurred");
thrown.expectCause(instanceOf(IllegalStateException.class));
foo.doStuff();
}
}
While this approach attempts to fix the caveats of @Test
with expected
to assert the exception message and cause, it also has issues when it comes to false positives:
@Test
public void prepareToDoStuff_shouldSucceed_doStuff_shouldThrowException() {
thrown.expect(FooException.class);
thrown.expectMessage("An exception has occurred");
thrown.expectCause(instanceOf(IllegalStateException.class));
// This method may throw a FooException, which may lead to a false positive result
foo.prepareToDoStuff();
// This is the method that is supposed to throw the actual FooException being asserted
foo.doStuff();
}
Finally, if the test follows Behaviour-driven Development (BDD), you’ll find that ExpectedException
doesn’t use such writing style.
Using assertThrows
from JUnit 5
JUnit 5 aims to solve some problems of JUnit 4 and also takes advantage of Java 8 features, such as lambdas.
When it comes to exceptions, the @Test
annotation no longer can be used for indicate the expected exception. As described above, this approach may lead to false positives and doesn’t allow asserting on the exception itself.
As replacement, JUnit 5 introduced the assertThrows()
method: It asserts that the execution of the supplied executable throws an exception of the expected type and returns the exception instance, so assertions can be performed on it.
The test will fail if no exception is thrown, or if an exception of a different type is thrown.
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import static org.hamcrest.CoreMatchers.instanceOf;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.jupiter.api.Assertions.assertThrows;
public class UsingAssertThrowsFromJUnit5 {
private Foo foo = new Foo();
@Test
@DisplayName("doStuff method should throw exception")
public void doStuff_shouldThrowException() {
Throwable thrown = assertThrows(FooException.class, () -> foo.doStuff());
assertThat(thrown.getMessage(), is("An exception has occurred"));
assertThat(thrown.getCause(), instanceOf(IllegalStateException.class));
}
}
Using AssertJ
AssertJ provides a rich API for fluent assertions in Java. It aims to improve the test code readability and make the maintenance of tests easier by providing strongly-typed assertions and intuitive failure messages.
If your tests use at least Java 8, then you can use AssertJ 3.x and leverage on lambdas for asserting exceptions:
import org.junit.Test;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.assertj.core.api.Assertions.catchThrowable;
public class UsingAssertJWithJava8 {
private Foo foo = new Foo();
@Test
public void doStuff_shouldThrowException_1() {
assertThatExceptionOfType(FooException.class)
.isThrownBy(() -> foo.doStuff())
.withMessage("An exception has occurred")
.withCauseExactlyInstanceOf(IllegalStateException.class);
}
@Test
public void doStuff_shouldThrowException_2() {
assertThatThrownBy(() -> foo.doStuff())
.isInstanceOf(FooException.class)
.hasMessage("An exception has occurred")
.hasCauseExactlyInstanceOf(IllegalStateException.class);
}
@Test
public void doStuff_shouldThrowException_3() {
Throwable thrown = catchThrowable(() -> foo.doStuff());
assertThat(thrown)
.isInstanceOf(Exception.class)
.hasMessage("An exception has occurred")
.hasCauseExactlyInstanceOf(IllegalStateException.class);
}
@Test
public void doStuff_shouldThrowException_4() {
FooException thrown = catchThrowableOfType(() -> foo.doStuff(), FooException.class);
assertThat(thrown)
.hasMessage("An exception has occurred")
.hasCauseExactlyInstanceOf(IllegalStateException.class);
}
}
If your tests use Java 7, then you can use the try
—catch
with fail()
approach with AssertJ 2.x and perform fluent assertions on the exception that has been thrown:
import org.junit.Test;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.failBecauseExceptionWasNotThrown;
import static org.junit.Assert.fail;
public class UsingAssertJWithJava7 {
private Foo foo = new Foo();
@Test
public void doStuff_shouldThrowException_1() {
try {
foo.doStuff();
fail("Expected exception has not been thrown");
} catch (FooException e) {
assertThat(e)
.hasMessage("An exception has occurred")
.hasCauseExactlyInstanceOf(IllegalStateException.class);
}
}
@Test
public void doStuff_shouldThrowException_2() {
try {
foo.doStuff();
failBecauseExceptionWasNotThrown(FooException.class);
} catch (FooException e) {
assertThat(e)
.hasMessage("An exception has occurred")
.hasCauseExactlyInstanceOf(IllegalStateException.class);
}
}
}
Bottom line and my thoughts
After evaluating the approaches for asserting exceptions described above, I would avoid both @Test
with expected
and @Rule
with ExpectedException
approaches, as they may lead to false positive results.
For Java 7, simply stick to the try
—catch
with fail()
approach, even if the test look a bit clumsy.
If you are using at least Java 8 (which I really hope you are), then you can leverage the power of lambdas for assertions. And I strongly encourage you to consider using AssertJ, as it provides a fluent API and the assertions are very close to plain English, which boosts the readability of your tests.
Иногда возникновение исключения является ожидаемым поведением системы, и в тестах нужно проверять, что оно действительно возникает.
Ниже описаны пять способов, как в тестовом фреймворке JUnit перехватить ожидаемое исключение и проверить его свойства. Первые четыре из них можно использовать в JUnit 4, а последний способ использует новые возможности JUnit 5.
В качестве примера для демонстрации возьмём тест для функции стандартной библиотеки, создающей временный файл. Будем проверять, что при попытке создания файла в несуществующей директории возникает исключение типа IOException
. При этом предварительно в том же самом тесте создаётся временная директория и тут же удаляется, так что мы получаем гарантированно несуществующую директорию, в которой и пытаемся создать файл:
import org.junit.Test;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
public class MyTest {
@Test
public void testCreateTempFile() throws IOException {
Path tmpDir = Files.createTempDirectory("tmp");
tmpDir.toFile().delete();
Path tmpFile = Files.createTempFile(tmpDir, "test", ".txt");
}
}
Разумеется, в таком виде тест упадёт, а в отчёте будет написано, что возникло исключение. А нам нужно, чтобы тест в этом случае наоборот помечался как успешный. Посмотрим, как это можно исправить.
1. @Test
Самый простой способ сообщить тестовому фреймворку о том, что ожидается исключение – указать дополнительный параметр expected
в аннотации @Test
:
import org.junit.Test;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
public class MyTest {
@Test(expected = IOException.class)
public void testCreateTempFile() throws IOException {
Path tmpDir = Files.createTempDirectory("tmp");
tmpDir.toFile().delete();
Path tmpFile = Files.createTempFile(tmpDir, "test", ".txt");
}
}
Этот параметр должен содержать тип ожидаемого исключения. Если возникнет исключение именно такого типа – тест пройдёт успешно. Если возникнет исключение другого типа или не возникнет вовсе – тест упадёт.
Достоинства:
- Простота и краткость.
Недостатки:
- Нельзя проверить текст сообщения или другие свойства возникшего исключения.
- Нельзя понять, где именно возникло исключение. В рассматриваемом примере оно могло быть выброшено не тестируемой функцией, а чуть раньше, при попытке создать временную директорию. Тест даже не смог добраться до вызова тестируемой функции – но при этом в отчёте он помечается как успешно пройденный!
Вторая из упомянутых проблем настолько ужасна, что я никому никогда не рекомендую использовать этот способ.
2. try-catch
Оба недостатка можно устранить, если перехватывать исключение явно при помощи конструкции try-catch
:
import org.junit.Assert;
import org.junit.Test;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
public class MyTest {
@Test
public void testCreateTempFile() throws IOException {
Path tmpDir = Files.createTempDirectory("tmp");
tmpDir.toFile().delete();
try {
Path tmpFile = Files.createTempFile(tmpDir, "test", ".txt");
Assert.fail("Expected IOException");
} catch (IOException thrown) {
Assert.assertNotEquals("", thrown.getMessage());
}
// дальше идёт какой-то другой код
// в нём тоже может появиться неожиданный IOException
// если это случится -- тест упадёт
}
}
Если исключение возникает до блока try
– тест падает, мы узнаём о том, что у него возникли проблемы.
Если тестируемая функция не выбрасывает вообще никакого исключения – мы попадаем на fail()
в следующей строке, тест падает.
Если она выбрасывает исключение неподходящего типа – блок catch
не ловит его, тест опять таки падает.
Успешно он завершается только тогда, когда тестируемая функция выбрасывает исключение нужного типа.
Тест стал более надёжным, он больше не пропускает баги. А в блоке catch
можно проверить свойства пойманного исключения.
3. @Rule
Однако работать с конструкцией try-catch
неудобно.
Чтобы избавиться от неё, можно воспользоваться правилом ExpectedException
, входящим в стандартный дистрибутив JUnit 4:
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.not;
public class MyTest {
@Rule
public ExpectedException thrown = ExpectedException.none();
@Test
public void testCreateTempFile() throws IOException {
Path tmpDir = Files.createTempDirectory("tmp");
tmpDir.toFile().delete();
thrown.expect(IOException.class);
thrown.expectMessage(not(equalTo("")));
Path tmpFile = Files.createTempFile(tmpDir, "test", ".txt");
thrown = ExpectedException.none();
// дальше идёт какой-то другой код
// в нём тоже может появиться неожиданный IOException
// если это случится -- тест упадёт
}
}
Теперь код имеет простую плоскую структуру, хотя общее количество строк кода, к сожалению, увеличилось.
Но главная проблема этого способа заключается в том, что проверки в таком стиле выглядят противоестественно – сначала описывается поведение, а потом вызывается функция. Конечно, это дело вкуса, но мне нравится, когда проверки располагаются после вызова тестируемой функции.
4. AssertJ / catch-throwable
Более красивый способ, использующий возможности Java 8, предлагают дополнительные библиотеки, такие как AssertJ или catch-throwable. Вот пример работы с AssertJ:
import org.junit.Test;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.catchThrowable;
public class MyTest {
@Test
public void testCreateTempFile() throws IOException {
Path tmpDir = Files.createTempDirectory("tmp");
tmpDir.toFile().delete();
Throwable thrown = catchThrowable(() -> {
Files.createTempFile(tmpDir, "test", ".txt");
});
assertThat(thrown).isInstanceOf(IOException.class);
assertThat(thrown.getMessage()).isNotBlank();
// дальше идёт какой-то другой код
// в нём тоже может появиться неожиданный IOException
// если это случится -- тест упадёт
}
}
Обращение к тестирумой функции оформлено в виде лямбда-выражения (анонимной функции), которое передаётся в “ловушку” для исключений catchThrowable
. Она перехватывает возникающее исключение и возвращает его как результат своей работы, давая возможность сохранить его в переменную и затем проверить его свойства. При этом проверки находятся после вызова тестируемой функции, читать код легче.
А если исключение не возникнет – “ловушка” сама выбросит исключение и тест упадёт.
5. JUnit 5
Но почему нужно использовать какие-то дополнительные библиотеки, почему тестовые фреймворки сами не предоставляют удобных возможностей для работы с ожидаемыми исключениями?
Уже предоставляют. Перехват исключений в JUnit 5 выглядит очень похоже на предыдущий пример:
import org.junit.jupiter.api.Test;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertThrows;
public class MyTest {
@Test
public void testCreateTempFile() throws IOException {
Path tmpDir = Files.createTempDirectory("tmp");
tmpDir.toFile().delete();
Throwable thrown = assertThrows(IOException.class, () -> {
Files.createTempFile(tmpDir, "test", ".txt");
});
assertNotNull(thrown.getMessage());
// дальше идёт какой-то другой код
// в нём тоже может появиться неожиданный IOException
// если это случится -- тест упадёт
}
}
Раньше такая возможность в JUnit отсутствовала, потому что предыдущие версии JUnit были ориентированы на более старые версии Java, где не было лямбда-выражений и написать подобный код было просто невозможно. Да, можно сделать нечто подобное с помощью анонимных классов, но это выглядит настолько ужасно, что конструкция try-catch
кажется верхом изящества.
Так что если вам приходится писать тесты, в которых проверяется возникновение исключений – есть повод присмотреться к новым возможностям JUnit 5.
In this JUnit article, we will discuss how to assert the expected exceptions thrown by the method.
1. JUnit5 – assertThrows
JUnit5 Jupiter Assertions API introduces a static method assertThrows
to assert the expected exceptions.
There are multiple overloaded methods of assertThrows. All of these methods are public static and return type of Throwable.
T assertThrows(Class expectedType, Executable executable) T assertThrows(Class expectedType, Executable executable, String message) T assertThrows(Class expectedType, Executable executable, Supplier messageSupplier)
Two important parameters it expects are
- Type of exception expected
- An executable that is expected to throw an exception. Here we can pass the code under test as a lambda expression or as a method reference.
If the executable blocks throw the expected( or any of its child) exception then the test will pass else it will fail.
@Test void assertNullPointerException() { var message = "test exception"; var expectedException = assertThrows( NullPointerException.class, () -> { throw new NullPointerException(message); }); assertEquals(message, expectedException.getMessage()); }
Since assertThrows returns a Throwable we can use it to verify the message or other details of a Throwable.
It is also important to note that expected exception is valid for the mentioned exception and all of its child classes as well.
Let’s implement the previous example by replacing the expected exception from NullPointerException with RuntimeException. New test is valid and will give the same result.
assertThrows( RuntimeException.class, () -> { throw new NullPointerException(message); });
Read More: assertDoesNotThrow in JUnit5
2. JUnit4
JUnit4 provides two different ways to assert the exceptions.
Let’s discuss @Test annotation and ExpectedException rule in detail.
2.1. @Test – expected
In JUnit4, @Test annotation provides the expected attribute which can simply be used to define the exception class we are excepting.
If the executable blocks throw the expected( or any of its child) exception then the test will pass else it will fail.
@Test(expected = NullPointerException.class) void assertNullPointerException() { var message = "test exception" throw new NullPointerException(message); }
This method of asserting an exception is good if we just want to verify be exception type. To check the assertion details let’s discuss ExpectedException Rule.
2.2. ExpectedException Rule
ExpectedException is a class in JUnit4 that can be used to verify exceptions thrown by a method as well its details like the message, cause, etc.
@Rule public ExpectedException expectedException = ExpectedException.none(); @Test public void throwsExcept() { var message = "test exception" expectedException.expect(NullPointerException.class); expectedException.expectMessage(message); throw new NullPointerException(message); }
In the example above we have used ExpectedException to verify the type and message of the exception thrown by the test method.
Complete code samples are present on Github project.
An investment in knowledge always pays the best interest. I hope you like the tutorial. Do come back for more because learning paves way for a better understanding
Do not forget to share and Subscribe.
Happy coding!! 😊
Recommended —
Содержание
- Ожидаемое исключение JUnit 5
- 1. Assertions API assertThrows ()
- 1.1. Синтаксис
- 1.2. Вывод теста
- 2. Ожидаемое исключение генерируемое в тесте
- 3. Сгенерировано исключение другого типа, или не сгенерировано исключение
- Java junit assert exception
- Assert
- assertTrue
- assertTrue
- assertFalse
- assertFalse
- assertEquals
- assertEquals
- assertNotEquals
- assertNotEquals
- assertNotEquals
- assertNotEquals
- assertNotEquals
- assertNotEquals
- assertNotEquals
- assertArrayEquals
- assertArrayEquals
- assertArrayEquals
- assertArrayEquals
- assertArrayEquals
- assertArrayEquals
- assertArrayEquals
- assertArrayEquals
- assertArrayEquals
- assertArrayEquals
- assertArrayEquals
- assertArrayEquals
- assertArrayEquals
- assertArrayEquals
- assertArrayEquals
- assertArrayEquals
- assertArrayEquals
- assertArrayEquals
- assertEquals
- assertEquals
- assertNotEquals
- assertEquals
- assertEquals
- assertEquals
- assertEquals
- assertEquals
- assertEquals
- assertNotNull
- assertNotNull
- assertNull
- assertNull
- assertSame
- assertSame
- assertNotSame
- assertNotSame
- assertEquals
- assertEquals
- assertThat
- assertThat
- assertThrows
Ожидаемое исключение JUnit 5
Это продолжение туториала по JUnit 5. Введение опубликовано здесь.
В JUnit 5, чтобы написать тестовый код, который, как ожидается, вызовет исключение, мы должны использовать Assertions.assertThrows().
В данном примере ожидается, что тестовый код в комментированном блоке вызовет исключение типа ApplicationException .
Использование Assertions.assertThrows()
Оглавление
Assertions API assertThrows ().
Ожидаемое исключение генерируется в тесте.
Сгенерировано исключение другого типа, или не сгенерировано исключение
1. Assertions API assertThrows ()
1.1. Синтаксис
Метод assertThrows() утверждает, что выполнение прилагаемого исполняемого блока или лямбда — выражения вызывает исключение типа expectedType . Это перегруженный метод, который принимает следующие параметры.
expectedType — ожидается, что тестовый код вызовет исключение этого типа.
message — если исполняемый код не вызывает никаких исключений, это сообщение будет напечатано вместе с результатом FAIL.
messageSupplier — сообщение будет извлечено из него в случае неудачи теста.
1.2. Вывод теста
Если в блоке не было генерировано исключение, executable , то assertThrows() вернет FAIL .
Если выбрасывается исключение другого типа, assertThrows() будет FAIL .
Если блок кода вызывает исключение класса, который является подтипом исключения expectedType , только тогда assertThrows() вернет PASS .
Например, если мы ожидаем, IllegalArgumentException и тест выдает ошибку NumberFormatException, тогда и вывод теста будет PASS потому что NumberFormatException расширяет класс IllegalArgumentException.
Кроме того, если мы передадим Exception.class в качестве ожидаемого типа исключения, любое исключение, выброшенное из исполняемого блока, сделает результат assertion равным PASS , поскольку Exception является супертипом для всех исключений.
2. Ожидаемое исключение генерируемое в тесте
Ниже приведен очень простой тест, который ожидает, что исключение NumberFormatException будет сгенерировано при выполнении предоставленного блока кода.
Оба теста выдают PASS
В тесте testExpectedException , исполняемый код Integer.parseInt(«One») генерирует исключение NumberFormatException, если аргумент метода не является допустимым текстовым представлением числа. Метод assertThrows() ожидает это исключение, так что результат теста PASS .
В тесте testExpectedExceptionWithParentType , мы выполняем тот же код, но на этот раз мы принимаем исключение IllegalArgumentException , родительское для NumberFormatException . Этот тест тоже проходит.
3. Сгенерировано исключение другого типа, или не сгенерировано исключение
Если исполняемый код вызывает исключение любого другого типа, то результат теста будет FAIL .
И даже если исполняемый код не вызывает никаких исключений, результат теста тоже будет FAIL .
Например, в приведенном ниже примере «1» это допустимое число, поэтому исключение не возникает. Этот тест завершится ошибкой с сообщением в консоли.
В этом посте мы узнали, как написать тест, ожидающий возникновение исключений. Эти тесты полезны при тестировании кода, написанного в блоках catch.
Источник
Java junit assert exception
A set of assertion methods useful for writing tests. Only failed assertions are recorded. These methods can be used directly: Assert.assertEquals(. ) , however, they read better if they are referenced through static import:
Constructor Summary | |
---|---|
protected | Assert () Protect constructor since it is a static only class |
Method Summary | |
---|---|
static void | assertArrayEquals (boolean[] expecteds, boolean[] actuals) Asserts that two boolean arrays are equal. |
static void | assertArrayEquals (byte[] expecteds, byte[] actuals) Asserts that two byte arrays are equal. |
static void | assertArrayEquals (char[] expecteds, char[] actuals) Asserts that two char arrays are equal. |
static void | assertArrayEquals (double[] expecteds, double[] actuals, double delta) Asserts that two double arrays are equal. |
static void | assertArrayEquals (float[] expecteds, float[] actuals, float delta) Asserts that two float arrays are equal. |
static void | assertArrayEquals (int[] expecteds, int[] actuals) Asserts that two int arrays are equal. |
static void | assertArrayEquals (long[] expecteds, long[] actuals) Asserts that two long arrays are equal. |
static void | assertArrayEquals (Object[] expecteds, Object[] actuals) Asserts that two object arrays are equal. |
static void | assertArrayEquals (short[] expecteds, short[] actuals) Asserts that two short arrays are equal. |
static void | assertArrayEquals (String message, boolean[] expecteds, boolean[] actuals) Asserts that two boolean arrays are equal. |
static void | assertArrayEquals (String message, byte[] expecteds, byte[] actuals) Asserts that two byte arrays are equal. |
static void | assertArrayEquals (String message, char[] expecteds, char[] actuals) Asserts that two char arrays are equal. |
static void | assertArrayEquals (String message, double[] expecteds, double[] actuals, double delta) Asserts that two double arrays are equal. |
static void | assertArrayEquals (String message, float[] expecteds, float[] actuals, float delta) Asserts that two float arrays are equal. |
static void | assertArrayEquals (String message, int[] expecteds, int[] actuals) Asserts that two int arrays are equal. |
static void | assertArrayEquals (String message, long[] expecteds, long[] actuals) Asserts that two long arrays are equal. |
static void | assertArrayEquals (String message, Object[] expecteds, Object[] actuals) Asserts that two object arrays are equal. |
static void | assertArrayEquals (String message, short[] expecteds, short[] actuals) Asserts that two short arrays are equal. |
static void | assertEquals (double expected, double actual) Deprecated. Use assertEquals(double expected, double actual, double delta) instead |
static void | assertEquals (double expected, double actual, double delta) Asserts that two doubles are equal to within a positive delta. |
static void | assertEquals (float expected, float actual, float delta) Asserts that two floats are equal to within a positive delta. |
static void | assertEquals (long expected, long actual) Asserts that two longs are equal. |
static void | assertEquals (Object[] expecteds, Object[] actuals) Deprecated. use assertArrayEquals |
static void | assertEquals (Object expected, Object actual) Asserts that two objects are equal. |
static void | assertEquals (String message, double expected, double actual) Deprecated. Use assertEquals(String message, double expected, double actual, double delta) instead |
static void | assertEquals (String message, double expected, double actual, double delta) Asserts that two doubles are equal to within a positive delta. |
static void | assertEquals (String message, float expected, float actual, float delta) Asserts that two floats are equal to within a positive delta. |
static void | assertEquals (String message, long expected, long actual) Asserts that two longs are equal. |
static void | assertEquals (String message, Object[] expecteds, Object[] actuals) Deprecated. use assertArrayEquals |
static void | assertEquals (String message, Object expected, Object actual) Asserts that two objects are equal. |
static void | assertFalse (boolean condition) Asserts that a condition is false. |
static void | assertFalse (String message, boolean condition) Asserts that a condition is false. |
static void | assertNotEquals (double unexpected, double actual, double delta) Asserts that two doubles are not equal to within a positive delta. |
static void | assertNotEquals (float unexpected, float actual, float delta) Asserts that two floats are not equal to within a positive delta. |
static void | assertNotEquals (long unexpected, long actual) Asserts that two longs are not equals. |
static void | assertNotEquals (Object unexpected, Object actual) Asserts that two objects are not equals. |
static void | assertNotEquals (String message, double unexpected, double actual, double delta) Asserts that two doubles are not equal to within a positive delta. |
static void | assertNotEquals (String message, float unexpected, float actual, float delta) Asserts that two floats are not equal to within a positive delta. |
static void | assertNotEquals (String message, long unexpected, long actual) Asserts that two longs are not equals. |
static void | assertNotEquals (String message, Object unexpected, Object actual) Asserts that two objects are not equals. |
static void | assertNotNull (Object object) Asserts that an object isn’t null. |
static void | assertNotNull (String message, Object object) Asserts that an object isn’t null. |
static void | assertNotSame (Object unexpected, Object actual) Asserts that two objects do not refer to the same object. |
static void | assertNotSame (String message, Object unexpected, Object actual) Asserts that two objects do not refer to the same object. |
static void | assertNull (Object object) Asserts that an object is null. |
static void | assertNull (String message, Object object) Asserts that an object is null. |
static void | assertSame (Object expected, Object actual) Asserts that two objects refer to the same object. |
static void | assertSame (String message, Object expected, Object actual) Asserts that two objects refer to the same object. |
static
void |
assertThat (String reason, T actual, Matcher matcher) Deprecated. use org.hamcrest.MatcherAssert.assertThat() |
static
void |
assertThat (T actual, Matcher matcher) Deprecated. use org.hamcrest.MatcherAssert.assertThat() |
static
T |
assertThrows (Class expectedThrowable, ThrowingRunnable runnable) Asserts that runnable throws an exception of type expectedThrowable when executed. |
static
T |
assertThrows (String message, Class expectedThrowable, ThrowingRunnable runnable) Asserts that runnable throws an exception of type expectedThrowable when executed. |
static void | assertTrue (boolean condition) Asserts that a condition is true. |
static void | assertTrue (String message, boolean condition) Asserts that a condition is true. |
static void | fail () Fails a test with no message. |
static void | fail (String message) Fails a test with the given message. |
Methods inherited from class java.lang.Object |
---|
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait |
Constructor Detail |
---|
Assert
Method Detail |
---|
assertTrue
Parameters: message — the identifying message for the AssertionError ( null okay) condition — condition to be checked
assertTrue
Parameters: condition — condition to be checked
assertFalse
Parameters: message — the identifying message for the AssertionError ( null okay) condition — condition to be checked
assertFalse
Parameters: condition — condition to be checked
Parameters: message — the identifying message for the AssertionError ( null okay) See Also: AssertionError
assertEquals
Parameters: message — the identifying message for the AssertionError ( null okay) expected — expected value actual — actual value
assertEquals
Parameters: expected — expected value actual — the value to check against expected
assertNotEquals
Parameters: message — the identifying message for the AssertionError ( null okay) unexpected — unexpected value to check actual — the value to check against unexpected
assertNotEquals
Parameters: unexpected — unexpected value to check actual — the value to check against unexpected
assertNotEquals
Parameters: message — the identifying message for the AssertionError ( null okay) unexpected — unexpected value to check actual — the value to check against unexpected
assertNotEquals
Parameters: unexpected — unexpected value to check actual — the value to check against unexpected
assertNotEquals
Parameters: message — the identifying message for the AssertionError ( null okay) unexpected — unexpected value actual — the value to check against unexpected delta — the maximum delta between unexpected and actual for which both numbers are still considered equal.
assertNotEquals
Parameters: unexpected — unexpected value actual — the value to check against unexpected delta — the maximum delta between unexpected and actual for which both numbers are still considered equal.
assertNotEquals
Parameters: unexpected — unexpected value actual — the value to check against unexpected delta — the maximum delta between unexpected and actual for which both numbers are still considered equal.
assertArrayEquals
Parameters: message — the identifying message for the AssertionError ( null okay) expecteds — Object array or array of arrays (multi-dimensional array) with expected values. actuals — Object array or array of arrays (multi-dimensional array) with actual values Throws: org.junit.internal.ArrayComparisonFailure
assertArrayEquals
Parameters: expecteds — Object array or array of arrays (multi-dimensional array) with expected values actuals — Object array or array of arrays (multi-dimensional array) with actual values
assertArrayEquals
Parameters: message — the identifying message for the AssertionError ( null okay) expecteds — boolean array with expected values. actuals — boolean array with expected values. Throws: org.junit.internal.ArrayComparisonFailure
assertArrayEquals
Parameters: expecteds — boolean array with expected values. actuals — boolean array with expected values.
assertArrayEquals
Parameters: message — the identifying message for the AssertionError ( null okay) expecteds — byte array with expected values. actuals — byte array with actual values Throws: org.junit.internal.ArrayComparisonFailure
assertArrayEquals
Parameters: expecteds — byte array with expected values. actuals — byte array with actual values
assertArrayEquals
Parameters: message — the identifying message for the AssertionError ( null okay) expecteds — char array with expected values. actuals — char array with actual values Throws: org.junit.internal.ArrayComparisonFailure
assertArrayEquals
Parameters: expecteds — char array with expected values. actuals — char array with actual values
assertArrayEquals
Parameters: message — the identifying message for the AssertionError ( null okay) expecteds — short array with expected values. actuals — short array with actual values Throws: org.junit.internal.ArrayComparisonFailure
assertArrayEquals
Parameters: expecteds — short array with expected values. actuals — short array with actual values
assertArrayEquals
Parameters: message — the identifying message for the AssertionError ( null okay) expecteds — int array with expected values. actuals — int array with actual values Throws: org.junit.internal.ArrayComparisonFailure
assertArrayEquals
Parameters: expecteds — int array with expected values. actuals — int array with actual values
assertArrayEquals
Parameters: message — the identifying message for the AssertionError ( null okay) expecteds — long array with expected values. actuals — long array with actual values Throws: org.junit.internal.ArrayComparisonFailure
assertArrayEquals
Parameters: expecteds — long array with expected values. actuals — long array with actual values
assertArrayEquals
Parameters: message — the identifying message for the AssertionError ( null okay) expecteds — double array with expected values. actuals — double array with actual values delta — the maximum delta between expecteds[i] and actuals[i] for which both numbers are still considered equal. Throws: org.junit.internal.ArrayComparisonFailure
assertArrayEquals
Parameters: expecteds — double array with expected values. actuals — double array with actual values delta — the maximum delta between expecteds[i] and actuals[i] for which both numbers are still considered equal.
assertArrayEquals
Parameters: message — the identifying message for the AssertionError ( null okay) expecteds — float array with expected values. actuals — float array with actual values delta — the maximum delta between expecteds[i] and actuals[i] for which both numbers are still considered equal. Throws: org.junit.internal.ArrayComparisonFailure
assertArrayEquals
Parameters: expecteds — float array with expected values. actuals — float array with actual values delta — the maximum delta between expecteds[i] and actuals[i] for which both numbers are still considered equal.
assertEquals
Parameters: message — the identifying message for the AssertionError ( null okay) expected — expected value actual — the value to check against expected delta — the maximum delta between expected and actual for which both numbers are still considered equal.
assertEquals
Parameters: message — the identifying message for the AssertionError ( null okay) expected — expected value actual — the value to check against expected delta — the maximum delta between expected and actual for which both numbers are still considered equal.
assertNotEquals
Parameters: message — the identifying message for the AssertionError ( null okay) unexpected — unexpected value actual — the value to check against unexpected delta — the maximum delta between unexpected and actual for which both numbers are still considered equal.
assertEquals
Parameters: expected — expected long value. actual — actual long value
assertEquals
Parameters: message — the identifying message for the AssertionError ( null okay) expected — long expected value. actual — long actual value
assertEquals
assertEquals
assertEquals
Parameters: expected — expected value actual — the value to check against expected delta — the maximum delta between expected and actual for which both numbers are still considered equal.
assertEquals
Parameters: expected — expected value actual — the value to check against expected delta — the maximum delta between expected and actual for which both numbers are still considered equal.
assertNotNull
Parameters: message — the identifying message for the AssertionError ( null okay) object — Object to check or null
assertNotNull
Parameters: object — Object to check or null
assertNull
Parameters: message — the identifying message for the AssertionError ( null okay) object — Object to check or null
assertNull
Parameters: object — Object to check or null
assertSame
Parameters: message — the identifying message for the AssertionError ( null okay) expected — the expected object actual — the object to compare to expected
assertSame
Parameters: expected — the expected object actual — the object to compare to expected
assertNotSame
Parameters: message — the identifying message for the AssertionError ( null okay) unexpected — the object you don’t expect actual — the object to compare to unexpected
assertNotSame
Parameters: unexpected — the object you don’t expect actual — the object to compare to unexpected
assertEquals
Asserts that two object arrays are equal. If they are not, an AssertionError is thrown with the given message. If expecteds and actuals are null , they are considered equal.
Parameters: message — the identifying message for the AssertionError ( null okay) expecteds — Object array or array of arrays (multi-dimensional array) with expected values. actuals — Object array or array of arrays (multi-dimensional array) with actual values
assertEquals
Asserts that two object arrays are equal. If they are not, an AssertionError is thrown. If expected and actual are null , they are considered equal.
Parameters: expecteds — Object array or array of arrays (multi-dimensional array) with expected values actuals — Object array or array of arrays (multi-dimensional array) with actual values
assertThat
Asserts that actual satisfies the condition specified by matcher . If not, an AssertionError is thrown with information about the matcher and failing value. Example: org.hamcrest.Matcher does not currently document the meaning of its type parameter T . This method assumes that a matcher typed as Matcher can be meaningfully applied only to values that could be assigned to a variable of type T .
Type Parameters: T — the static type accepted by the matcher (this can flag obvious compile-time problems such as assertThat(1, is(«a»)) Parameters: actual — the computed value being compared matcher — an expression, built of Matcher s, specifying allowed values See Also: CoreMatchers
assertThat
Asserts that actual satisfies the condition specified by matcher . If not, an AssertionError is thrown with the reason and information about the matcher and failing value. Example: org.hamcrest.Matcher does not currently document the meaning of its type parameter T . This method assumes that a matcher typed as Matcher can be meaningfully applied only to values that could be assigned to a variable of type T .
Type Parameters: T — the static type accepted by the matcher (this can flag obvious compile-time problems such as assertThat(1, is(«a»)) Parameters: reason — additional information about the error actual — the computed value being compared matcher — an expression, built of Matcher s, specifying allowed values See Also: CoreMatchers
assertThrows
Parameters: expectedThrowable — the expected type of the exception runnable — a function that is expected to throw an exception when executed Returns: the exception thrown by runnable Since: 4.13
Источник