In this post under JUnit, I will show with example the purpose of “assertThrowsExactly” method and how it is different with “assertThrows” method.
I have explained with example, the purpose of “assertThrows” static method in previous posts.
For recap, “assertThrows” method asserts that the test method throws the expected exception. If the test method doesn’t throw the expected exception, it will fail the test case.
“assertThrowsExactly” static method is similar to “assertThrows”, it fails the test case whenever the test method doesn’t throw an expected exception.
Whereas the difference between these two is “assertThrows” also considers exceptions that are subclass of the expected exception, whereas “assertThrowsExactly” doesn’t consider the subclass of expected exception. In “assertThrowsExactly” static method, the exception thrown should be of same class as the expected exception.
For our example, lets test the below class
ExceptionThrower Example
package package17;
public class ExceptionThrower {
public void throwIllegalArgumentException() {
throw new IllegalArgumentException();
}
public void throwNumberFormatException() {
throw new NumberFormatException();
}
}
As you can see in the above code, they are two methods that throws exception. One method throws “IllegalArgumentException” and another throws “NumberFormatException”.
Note “NumberFormatException” exception is subclass of “IllegalArgumentException”.
Next lets see the Test class code
Test class
package package17;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertThrowsExactly;
public class ExceptionThrowerTest {
private ExceptionThrower exceptionThrower = new ExceptionThrower();
@Test
public void testThrowIllegalArgumentException() {
assertThrows(IllegalArgumentException.class, () -> {
exceptionThrower.throwIllegalArgumentException();
});
}
@Test
public void testThrowNumberFormatException() {
assertThrows(IllegalArgumentException.class, () -> {
exceptionThrower.throwNumberFormatException();
});
}
@Test
public void testAssertThrowsExactly() {
assertThrowsExactly(IllegalArgumentException.class, () -> {
exceptionThrower.throwNumberFormatException();
});
}
}
In the above test class, the test case “testThrowIllegalArgumentException” passes successfully.
Here we are testing that the test method throw “IllegalArgumentException”, which the test method is doing.
So this test case passes successfully
The next test case “testThrowNumberFormatException” also passes successfully.
Here we are testing whether the test method throw “IllegalArgumentException” or not.
Instead the test method is throwing “NumberFormatException” which is a subclass of “IllegalArgumentException” exception.
Since the “assertThrows” allows subclasses of the expected exception, the test case passes successfully.
The next test case “testAssertThrowsExactly” fails. Here we are testing that the test method throw “IllegalArgumentException”, but the test method is throwing “NumberFormatException” which is a subclass of “IllegalArgumentException” exception.
Since “assertThrowsExactly” doesn’t consider subclasses of the expected exception, the test case fails.
So in other words we can use “assertThrowsExactly” assert method only when we want to make sure the test method will throw the same exact exception and not any subclasses.