With JUnit 4.12 there are several ways to test code for expected exceptions.
try-catch
We can simply use Java's try-catch.
@Test
public void testInvalidData() {
prepareTestData();
try {
userService.fetchUser(1234);
Assert.fail("IllegalArgumentException not thrown");
} catch (IllegalArgumentException expected) {
}
}
Whenever we use this approach, we have to make sure to call Assert.fail(...) in case the expected exception was not thrown.
Annotation Attribute
As you already mentioned, the @Test has an attribute to declare the expected exception.
@Test(expected = IllegalArgumentException.class)
public void testInvalidData() {
prepareTestData();
// should throw IllegalArgumentException
userService.fetchUser(1234);
}
The test is green if the test method throws the exception. The test is red if the test method throws no exception or a different exception.
This has one big disadvantage: We can't figure out which instruction throws the IllegalArgumentException. If prepareTestData(); throws the exception, the test is still green.
Rule ExpectedException
JUnit 4 contains the built-in rule ExpectedException. (please remember that JUnit 5 uses extensions instead of rules)
@Rule
public ExpectedException thrown = ExpectedException.none();
@Test
public void testInvalidData() {
prepareTestData();
thrown.expect(IllegalArgumentException.class);
userService.fetchUser(1234);
}
This approach is similar to try-catch and @Test(expected = ...), but we can control from which point the exception is expected.
assertThrows
AssertJ and JUnit 5 provide methods to assert that a specific code block throws a specific exception.
@Test
public void testInvalidData() {
prepareTestData();
Assertions.assertThrows(IllegalArgumentException.class, () -> {
userService.fetchUser(1234);
});
}
Assertions.assertThrows also returns the exception object to execute further asserts, e.g. to assert the message.
Summary
I try to use assertThrows as often as possible because the test code gets both readable and flexible. But all the other mentioned approaches are also valid if correctly used.