JUnit Test Exception Examples - How to assert an exception is thrown
- Details
- Written by Nam Ha Minh
- Last Updated on 05 August 2019   |   Print Email
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); }); }
@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:
- JUnit Homepage
- assertThrows() method
- Executable interface
- @Test annotation (JUnit 4)
- ExpectedException class
Other JUnit Tutorials:
- JUnit Tutorial for beginner with Eclipse
- How to compile and run JUnit tests in command line
- JUnit Test Suite Example - How to create and run test suite in command line and Eclipse
Comments