JUnit 5 Expected Exception – assertThrows() Example

In JUnit 5, to write the test code that is expected to throw an exception, we should use Assertions.assertThrows(). The following test is expected to throw an exception of type ApplicationException or its subtype.

@Test
void testExpectedException() {

  ApplicationException thrown = Assertions.assertThrows(ApplicationException.class, () -> {
           //Code under test
  });

  Assertions.assertEquals("some message", thrown.getMessage());
}

Note that in JUnit 4, we needed to use @Test(expected = NullPointerException.class) syntax.

1. Assertions assertThrows() API

1.1. Syntax

The assertThrows() method asserts that execution of the supplied executable block or lambda expression throws an exception of the expectedType. It is an overloaded method and takes the following parameters.

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 – Test code is expected to throw an exception of this type.
  • message – If the executable code does not throw any exception, this message will be printed along with the FAIL result.
  • messageSupplier – The message will be retrieved from it in case the test fails.

1.2. Matching Exception Type: PASS vs FAIL

The assertThrows() will FAIL:

  • If no exception is thrown from the executable block
  • If an exception of a different type is thrown

The assertThrows() will PASS:

  • If the code block throws an exception of the specified type or a subtype. For example, if we are expecting IllegalArgumentException and the test throws NumberFormatException then also the test will PASS because NumberFormatException extends IllegalArgumentException class.

Note that if we pass Exception.class as the expected exception type, any exception thrown from the executable block will make the assertion PASS since Exception is the super-type for all exceptions.

2. Demo – Expected Exception is Thrown

Given below is a very simple test that expects NumberFormatException to be thrown when the supplied code block is executed.

@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");
	});
}
  • In testExpectedException, The executable code is Integer.parseInt("One") which throws NumberFormatException if method argument is not a valid numeric number. The assertThrows() the method expects – so this exception so the test result is PASS.
  • In testExpectedExceptionWithParentType, we are executing the same code but this time we are excepting IllegalArgumentException which is the parent of NumberFormatException. This test also passes.

3. Demo – A Different Exception Type is Thrown, or No Exception

If the executable code throws any other exception type, then the test will FAIL. And even if the executable code does not throw any exception then also test will FAIL.

For example, in below example "1" is a valid number so no exception will be thrown. This test will fail with the message in the console.

@Test
void testExpectedExceptionFail() {
 
	NumberFormatException thrown = Assertions
				.assertThrows(NumberFormatException.class, () -> {
					Integer.parseInt("1");
				}, "NumberFormatException error was expected");
	
	Assertions.assertEquals("Some expected message", thrown.getMessage());
}
Junit message

In this post, we learned how to write a test that expects exceptions to be thrown. These tests are helpful in testing the code written in the catch blocks.

4. Expected Exception @Rule in JUnit 4

In JUnit 4, we can use the @Rule annotation along with ExpectedException to assert exceptions. The following class rewrites the previous example in JUnit 4 syntax.

import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;

public class MyTestClass {

    @Rule
    public ExpectedException expectedException = ExpectedException.none();

    @Test
    public void testExpectedException() {
        expectedException.expect(NumberFormatException.class);
        expectedException.expectMessage("For input string: \"One\"");
        Integer.parseInt("One");
    }

    @Test
    public void testExpectedExceptionWithParentType() {
        expectedException.expect(IllegalArgumentException.class);
        Integer.parseInt("One");
    }
}

Happy Learning !!

Sourcecode Download

Comments

Subscribe
Notify of
guest
0 Comments
Inline Feedbacks
View all comments

About Us

HowToDoInJava provides tutorials and how-to guides on Java and related technologies.

It also shares the best practices, algorithms & solutions and frequently asked interview questions.

Our Blogs

REST API Tutorial

Dark Mode

Dark Mode