assertThrows JUnit 5 | Java Fresher Interview
Fast recall
Quick revision
Core answer
assertThrowsExactly when the exact runtime class is required.Interview-ready guide
Interview answer
assertThrows runs one executable and returns the exception when the expected type or a subtype is thrown. If exact runtime type matters, use assertThrowsExactly.
I keep the lambda limited to the operation expected to fail, because setup inside it could throw the same type and make a weak test pass. I then inspect only stable details that belong to the contract. A domain error code may be stronger than an exact message if the message is intended for people and can change. A cause is worth checking when wrapping that cause is part of the behavior.
For example, a withdrawal test can assert InsufficientFundsException and then verify its availableBalance field. A broad type such as RuntimeException usually proves too little, while checking type, full message, cause, and every field without a contract makes the test brittle.
assertThrows JUnit 5 | Java Fresher Interview
Direct Answer
assertThrows(Type.class, executable) verifies that the executable throws the given type or a subtype and returns the exception object. Use the most specific contract type, keep the executable small, and inspect a stable code, field, cause, or message only when relevant. Use assertThrowsExactly when the exact runtime class is required.
Deep Dive & Architecture
An exception test is strongest when it verifies the full public contract, not merely that some failure happened. assertThrows accepts an expected class and an executable, then returns the caught exception. Matching includes subclasses, so the expected class should be as specific as the contract allows.
For example, a payment service may throw PaymentRejectedException with a stable error code while wrapping a gateway exception as its cause. The test can capture that object, check its code, and check getCause() without depending on a full message that contains changing values. Put only service.pay(request) inside the lambda so an exception from test setup cannot produce a false positive. When exact runtime type matters, JUnit also provides assertThrowsExactly.
Code Example
// Custom exception with a field
class PaymentException extends RuntimeException {
final String code;
PaymentException(String code, String msg, Throwable cause) {
super(msg, cause); this.code = code;
}
String code() { return code; }
}
@Test
void wrapsAndReportsPaymentFailure() {
var ex = assertThrows(PaymentException.class,
() -> service.charge(badCard));
assertEquals("CARD_DECLINED", ex.code()); // custom field
assertTrue(ex.getMessage().contains("declined")); // message
assertInstanceOf(GatewayTimeout.class, ex.getCause()); // wrapped cause
}
Common Mistakes & Pitfalls
- Broad superclass.
assertThrows(RuntimeException.class, ...)may accept unrelated failures; use the contract type. - Unstable detail checks. Assert a code, message, field, or cause only when it is part of the behavior being promised.
- Exact versus subtype.
assertThrowsaccepts subtypes; useassertThrowsExactlywhen exact runtime class is required. - Volatile text. Prefer a stable code or meaningful fragment when full message wording can change.
Check your understanding
Answer these without looking back at the article.
- What is the Arrange-Act-Assert (AAA) pattern in unit testing?
- How do you use assertThrows to test exception scenarios in JUnit 5?
- How do you test floating point numbers in JUnit 5?
Looking for a structured roadmap?
Every module on this page is also part of the full Java backend interview track.