Assert Thrown Exception in Java
JUnit 5, AssertJ
In this article, we will learn how to assert thrown exceptions in Java using JUnit 5 and AssertJ assertion libraries.
Overview
We usually write a unit test to verify the expected output from a piece of code. We also expect that this piece of code can throw an exception in some situations and we also want to cover those cases in our unit test.
It is recommended to cover all those exceptions that are expected to be thrown by the code. Let’s see how we can assert thrown exceptions using JUnit 5 and AssertJ.
Assert Thrown Exception
Let’s say, we have a method doStuff
in the class FooService
. This method can throw a NullPointerException when a null flag is passed in the argument.
public class FooService {
public void doStuff(Boolean flag) {
try{
if(flag){
// do stuff
}
}catch (Exception e){
throw new RuntimeException("Unexpected error occurred", e);
}
}
}
Junit 5 - assertThrows
In Junit 5, we can test that:-
- an exception of a specific type is expected to be thrown by the code using
assertThrows()
assertion. - an exception is not expected to be thrown by the code using
assertDoesNotThrow()
assertion.
assertThrows(ExpectedException.class, () -> methodCall)
assertDoesNotThrow(() -> methodCall)
Let’s look at the example usage of assertThrows
and assertDoesNotThrow
:-
import static org.junit.jupiter.api.Assertions.*;
FooService fooService = new FooService();
@Test
public void doStuff_testThrownException(){
// null is passed, expected NullPointerException
Throwable exception = assertThrows(RuntimeException.class, () -> fooService.doStuff(null));
assertEquals("Unexpected error occurred", exception.getMessage());
assertEquals(NullPointerException.class, exception.getCause().getClass());
}
@Test
public void doStuff_shouldNotThrowException(){
// method is expected to work fine without exception
assertDoesNotThrow(() -> fooService.doStuff(true));
}
Please note that assertThrows()
returns the Throwable
exception, which we used to assert the exception message and exception cause in the above example.
Let’s look at some more example usage:-
// Assert IllegalArgumentException
assertThrows(IllegalArgumentException.class, () -> Integer.valueOf("foo"));
// Assert IndexOutOfBoundsException
Exception e = assertThrows(IndexOutOfBoundsException.class, () -> Arrays.asList("foo", "bar").get(2));
assertEquals("Index 2 out of bounds for length 2", e.getMessage());
// Assert RuntimeException
String str = null;
assertThrows(RuntimeException.class, () -> str.equals("foo"));
// Assert NullPointerException - exact match
assertThrowsExactly(NullPointerException.class, () -> str.equals("foo"));
Also Read Unit Test with JUnit 5 in Java for more details.
AssertJ - assertThatExceptionOfType
In AssertJ, we can test that:-
- any type of exception is expected to be thrown by the code using
assertThatThrownBy()
assertion. - a specific type of exception is expected to be thrown by the code using
assertThatExceptionOfType()
assertion. - an exception is not expected to be thrown by the code using
assertThatNoException()
assertion.
assertThatThrownBy(() -> methodCall)
assertThatExceptionOfType(ExpectedException.class).isThrownBy(() -> methodCall)
assertThatNoException().isThrownBy(() -> methodCall)
Let’s look at the example usage:-
import static org.assertj.core.api.Assertions.*;
FooService fooService = new FooService();
@Test
public void doStuff_testThrownException(){
// null is passed, expected NullPointerException
// example 1: assert for any exception
assertThatThrownBy(() -> fooService.doStuff(null))
.isInstanceOf(RuntimeException.class)
.hasMessage("Unexpected error occurred")
.hasCauseInstanceOf(NullPointerException.class);
// example 2: assert for exception of type RuntimeException
assertThatExceptionOfType(RuntimeException.class)
.isThrownBy(() -> fooService.doStuff(null))
.withMessage("Unexpected error occurred")
.withCauseInstanceOf(NullPointerException.class);
// example 3: shortcut assert for RuntimeException
assertThatRuntimeException().isThrownBy(() -> fooService.doStuff(null))
.withMessage("Unexpected error occurred")
.withCauseInstanceOf(NullPointerException.class);
}
@Test
public void doStuff_shouldNotThrowException(){
// method is expected to work fine without exception
assertThatNoException().isThrownBy(() -> fooService.doStuff(true));
}
We can use any assertion out of assertThatThrownBy
, assertThatExceptionOfType
, and assertThatRuntimeException
to test RuntimeException, last one is more readable.
Shortcut Assertions
AssertJ comes with shortcut assertions for popular exceptions e.g. IndexOutOfBoundsException, IllegalArgumentException, and NullPointerException. Let’s look at them:-
@Test
public void testSomeMoreThrownException() {
assertThatIndexOutOfBoundsException().isThrownBy(() -> Arrays.asList("foo", "bar").get(2))
.withMessage("Index 2 out of bounds for length 2");
assertThatIllegalArgumentException().isThrownBy(() -> Integer.valueOf("foo"))
.isInstanceOf(NumberFormatException.class);
assertThatNullPointerException().isThrownBy(() -> {
String text = null;
text.equals("foo");
});
}
Also Read Unit Test with AssertJ in Java for more details.