JUnit – assertThrows()
In this tutorial, you will learn about the assertThrows()
method in JUnit, which is used to verify that a specific exception is thrown during the execution of a test. This assertion is used for testing error scenarios and ensuring that your code handles invalid inputs or unexpected conditions appropriately.
The assertThrows()
method is part of the Assertions
class in JUnit and is a key tool for validating exception handling. If the specified exception is not thrown, the test fails, providing immediate feedback about potential issues in your code’s error-handling logic.
Syntax of assertThrows()
The assertThrows()
method comes in two forms:
static <T extends Throwable> T assertThrows(Class<T> expectedType, Executable executable);
static <T extends Throwable> T assertThrows(Class<T> expectedType, Executable executable, String message);
– The first form validates that the executable
(a block of code) throws the specified expectedType
of exception.
– The second form includes a custom failure message, which is displayed if the test fails. This message helps in debugging.
Basic Example of assertThrows()
Let’s start with a simple example. We’ll test a method that divides two numbers and throws an ArithmeticException
when the divisor is zero:
import static org.junit.jupiter.api.Assertions.assertThrows;
import org.junit.jupiter.api.Test;
class DivisionTest {
int divide(int dividend, int divisor) {
if (divisor == 0) {
throw new ArithmeticException("Cannot divide by zero");
}
return dividend / divisor;
}
@Test
void testDivideByZero() {
DivisionTest test = new DivisionTest();
assertThrows(ArithmeticException.class, () -> test.divide(10, 0), "Expected ArithmeticException for division by zero.");
}
}
Explanation:
- Condition: The
divide()
method throws anArithmeticException
if the divisor is zero. - Assertion:
assertThrows()
validates that the exception is thrown as expected. - Message: If no exception is thrown, the test fails with the custom failure message.
Testing Custom Exceptions
The assertThrows()
method can also be used to test custom exceptions. Let’s validate a method that throws a CustomException
for invalid input:
import static org.junit.jupiter.api.Assertions.assertThrows;
import org.junit.jupiter.api.Test;
class CustomExceptionTest {
class CustomException extends RuntimeException {
CustomException(String message) {
super(message);
}
}
void validateInput(int input) {
if (input < 0) {
throw new CustomException("Input must be non-negative");
}
}
@Test
void testCustomException() {
CustomExceptionTest test = new CustomExceptionTest();
assertThrows(CustomException.class, () -> test.validateInput(-1), "Expected CustomException for negative input.");
}
}
Key Takeaways:
- Custom Exceptions:
assertThrows()
works seamlessly with user-defined exceptions. - Validation: The test ensures that invalid input is correctly handled by throwing the appropriate exception.
Capturing Exception Details
The assertThrows()
method returns the thrown exception, allowing you to capture and validate its details. Let’s extract and validate the exception message:
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertEquals;
import org.junit.jupiter.api.Test;
class ExceptionMessageTest {
void process(int input) {
if (input < 0) {
throw new IllegalArgumentException("Negative input: " + input);
}
}
@Test
void testExceptionMessage() {
ExceptionMessageTest test = new ExceptionMessageTest();
IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, () -> test.process(-5));
assertEquals("Negative input: -5", exception.getMessage(), "Exception message does not match.");
}
}
Explanation:
- Validation:
assertThrows()
captures the exception instance. - Message Check:
assertEquals()
validates that the exception message is as expected.
Testing Multiple Exception Scenarios
Use assertThrows()
to validate multiple exception scenarios. For example:
import static org.junit.jupiter.api.Assertions.assertThrows;
import org.junit.jupiter.api.Test;
class MultiScenarioTest {
void processInput(int input) {
if (input < 0) {
throw new IllegalArgumentException("Negative input not allowed");
}
if (input == 0) {
throw new IllegalStateException("Input cannot be zero");
}
}
@Test
void testMultipleExceptions() {
MultiScenarioTest test = new MultiScenarioTest();
assertThrows(IllegalArgumentException.class, () -> test.processInput(-1), "Expected IllegalArgumentException for negative input.");
assertThrows(IllegalStateException.class, () -> test.processInput(0), "Expected IllegalStateException for zero input.");
}
}
This example tests different invalid inputs, ensuring that each scenario throws the correct exception.
Common Mistakes with assertThrows()
- Not Testing All Scenarios: Ensure you test both valid and invalid inputs to cover all cases.
- Ignoring Exception Messages: Validate exception details to ensure meaningful error messages.
- Using Wrong Exception Type: Ensure the expected exception matches the actual exception type.
Best Practices for assertThrows()
- Validate Exception Details: Always check exception messages and other properties for accuracy.
- Use Descriptive Messages: Provide meaningful failure messages to simplify debugging.
- Combine with Other Assertions: Use
assertThrows()
alongside other assertions likeassertEquals()
for comprehensive validation.
Conclusion
The assertThrows()
method in JUnit is used for validating exception handling in your code. Whether you’re testing built-in exceptions, custom exceptions, or capturing exception details, assertThrows()
ensures that your code handles errors correctly and predictably.