In this JUnit tutorial, you will learn how to assert an exception is thrown by the code under test. Suppose that we want to test the exception thrown by the setName() method in the User class below:

package net.codejava;

public class User {
	private String name;
	
	public void setName(String name) {
		if (name == null) {
			throw new IllegalArgumentException("Username cannot be blank");
		} else {
			if (name.length() < 3) {
				throw new IllegalArgumentException("Username is too short");
			} else if (name.length() > 30) {
				throw new IllegalArgumentException("Username is too long");
			}
		}
		
		this.name = name;
	}
}
We will discuss how to test the exception in different versions of JUnit.

 

1. Test Exception in JUnit 5 - using assertThrows() method

JUnit 5 provides the assertThrows() method that asserts a piece of code throws an exception of an expected type and returns the exception:

assertThrows(Class<T> expectedType, Executable executable, String message)

You put the code that can throw exception in the execute() method of an Executable type - Executable is a functional interface defined by JUnit. The message is optional, to be included in the error message printed when the test fails.

For example, the following test class implements a test method that asserts IllegalArgumentException is thrown by the setName() method of the User class:

package net.codejava;

import static org.junit.jupiter.api.Assertions.assertThrows;

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.function.Executable;

public class UserTest {

	@Test
	public void testUsernameIsNull() {
		
		assertThrows(IllegalArgumentException.class, new Executable() {
			
			@Override
			public void execute() throws Throwable {
				User user = new User();
				user.setName(null);
			}
		});
	}
}
If the expected exception (IllegalArgumentException in this example) is thrown, the test succeeded, otherwise it fails.

You can see the above code uses an anonymous class of type Executable. Of course you can shorter the code with Lambda syntax:

@Test
public void testUsernameIsNull() {

	assertThrows(IllegalArgumentException.class, () -> {
		User user = new User();
		user.setName(null);
	});
}
 



You can obtain the returned exception to test further, e.g. assert the exception message:

@Test
public void testUsernameIsNull() {

	Throwable exception = assertThrows(
			IllegalArgumentException.class, () -> {
				User user = new User();
				user.setName(null);
			}
	);

	assertEquals("Username cannot be blank", exception.getMessage());
}
 

Similarly, the following method tests the case username is too short:

@Test
public void testUsernameTooShort() {
	Throwable exception = assertThrows(
			IllegalArgumentException.class, () -> {
				User user = new User();
				user.setName("Jo");
			}
	);

	assertEquals("Username is too short", exception.getMessage());		
}
 

And the following method tests the case username is too long:

@Test
public void testUsernameTooLong() {
	Throwable exception = assertThrows(
			IllegalArgumentException.class, () -> {
				User user = new User();
				user.setName("Pablo Diego Jose Franciso Picasso");
			}
	);

	assertEquals("Username is too long", exception.getMessage());		
}
 

2. Test Exception in JUnit 4

In JUnit 4.7 or above, you can test exception by using the @Rule annotation with an ExpectedException class, for example:

package net.codejava;

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

public class UserTest {

	@Rule
	public ExpectedException exception = ExpectedException.none();
	
	@Test
	public void testUsernameTooShort() {
		exception.expect(IllegalArgumentException.class);
		exception.expectMessage("Username is too short");
		
		User user = new User();
		user.setName("Jo");	
	}
}
The ExpectedException object is created as a rule that expects none exception is thrown so this rule doesn’t affect all existing test methods:

@Rule
public ExpectedException exception = ExpectedException.none();
Then in the test method you can use its expect() and expectMessage() to assert the type of expected exception and the exception message.

In older versions of JUnit 4, you can specify the expected exception in the @Test annotation like this:

@Test(expected = IllegalArgumentException.class)
public void testUsernameIsNull() {
	User user = new User();
	user.setName(null);
}
 

3. Test Exception in JUnit 3

In JUnit 3, or more exactly, in any versions of JUnit you can always use Java’s try-catch structure to test exception. Here’s an example:

package net.codejava;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;

import org.junit.Test;

public class UserTest {
	@Test
	public void testUserNameTooShort() {
		
		try {
			User user = new User();
			user.setName("Jo");
			
			fail();
		} catch (IllegalArgumentException ex) {
			assertEquals("Username is too short", ex.getMessage());
		}
	}
}
 

As you can see, we use the fail() statement at the end of the catch block so if the code doesn’t throw any exception, the test fails. And we catch the expected exception by the catch clause, in which we use assertEquals() methods to assert the exception message. You can use this structure to test any exceptions.

 

Video:

 

References:

 

Other JUnit Tutorials:


About the Author:

is certified Java programmer (SCJP and SCWCD). He began programming with Java back in the days of Java 1.4 and has been passionate about it ever since. You can connect with him on Facebook and watch his Java videos on YouTube.



Add comment

   


Comments 

#3Weston2021-09-22 13:56
This code literally saved my homework assignment, thank you so much!
Quote
#2Danny Tram2021-05-03 23:36
awesome. Very useful article. Keep it up!!
Quote
#1Ankit2020-09-04 04:36
please remove foramtting coming with copy and paste. it is irritating
Quote