Testing Exceptions with assertThrows() in JUnit 5
Use assertThrows() when you expect a piece of code to throw a specific exception.
Basic Syntax
ExceptionType exception = assertThrows(
ExceptionType.class,
() -> {
// code that should throw the exception
}
);
For JUnit 5, import it like this:
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertThrows;
Simple Example
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertThrows;
class DivisionTest {
@Test
void divideByZeroThrowsArithmeticException() {
assertThrows(ArithmeticException.class, () -> {
int result = 10 / 0;
});
}
}
If 10 / 0 throws an ArithmeticException, the test passes.
If no exception is thrown, or a different exception is thrown, the test fails.
Checking the Exception Message
assertThrows() returns the thrown exception, so you can inspect it.
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
class UserServiceTest {
@Test
void rejectsInvalidUserId() {
IllegalArgumentException exception = assertThrows(
IllegalArgumentException.class,
() -> validateUserId(-1)
);
assertEquals("User ID must be positive", exception.getMessage());
}
private void validateUserId(int userId) {
if (userId <= 0) {
throw new IllegalArgumentException("User ID must be positive");
}
}
}
Testing a Method That Throws an Exception
Suppose you have this method:
public int divide(int a, int b) {
if (b == 0) {
throw new IllegalArgumentException("Divider cannot be zero");
}
return a / b;
}
You can test it like this:
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
class CalculatorTest {
private final Calculator calculator = new Calculator();
@Test
void divideThrowsExceptionWhenDividerIsZero() {
IllegalArgumentException exception = assertThrows(
IllegalArgumentException.class,
() -> calculator.divide(10, 0)
);
assertEquals("Divider cannot be zero", exception.getMessage());
}
}
Short Form
If you only care that the exception is thrown, you do not need to store it:
@Test
void invalidInputThrowsException() {
assertThrows(
IllegalArgumentException.class,
() -> someMethod("invalid")
);
}
Important Notes
- The code that should throw the exception goes inside the lambda:
() -> ... - The expected exception type goes first:
IllegalArgumentException.class - The test passes only if that exception type, or a subclass of it, is thrown.
- If you want an exact exception type match, use
assertThrowsExactly().
Example:
@Test
void throwsExactlyIllegalArgumentException() {
assertThrowsExactly(
IllegalArgumentException.class,
() -> someMethod("invalid")
);
}
You would need this import:
import static org.junit.jupiter.api.Assertions.assertThrowsExactly;
Common Mistake
Do not call the method before assertThrows():
// Wrong
someMethod("invalid");
assertThrows(IllegalArgumentException.class, () -> {});
Instead, call the method inside the lambda:
// Correct
assertThrows(
IllegalArgumentException.class,
() -> someMethod("invalid")
);
Summary
Use assertThrows() like this:
@Test
void methodThrowsExpectedException() {
Exception exception = assertThrows(
Exception.class,
() -> methodThatShouldThrow()
);
assertEquals("Expected message", exception.getMessage());
}
It verifies that the code throws the expected exception and optionally lets you check details such as the exception message.
