Assert Thrown Exception in Java Assert Thrown Exception in Java

JUnit 5, AssertJ

Page content

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:-

  1. an exception of a specific type is expected to be thrown by the code using assertThrows() assertion.
  2. 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:-

  1. any type of exception is expected to be thrown by the code using assertThatThrownBy() assertion.
  2. a specific type of exception is expected to be thrown by the code using assertThatExceptionOfType() assertion.
  3. 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.