I am using JUnit 4.12
<dependency>
<groupId>pl.pragmatists</groupId>
<artifactId>JUnitParams</artifactId>
<version>1.0.5</version>
<scope>test</scope>
</dependency>
I wanted to know which one is most recommended to use
@Test(expected = Exception.class)
or Assertions.assertThrows(...)
With JUnit 4.12 there are several ways to test code for expected exceptions.
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.
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.
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.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With