junit 5 中推荐使用 assertthrows 验证异常,它执行代码块、捕获指定类型异常并返回异常对象供进一步断言(如消息、错误码);junit 4 不支持该方法,需用 @test(expected=...) 或已弃用的 expectedexception 规则。

JUnit 5 中直接用 assertThrows 即可验证异常,它会执行代码块、捕获指定类型的异常,并返回该异常对象供进一步断言(比如检查消息内容);JUnit 4 不支持该方法,需改用 @Test(expected = ...) 或 ExpectedException 规则(已弃用)。
JUnit 5:使用 assertThrows 基本写法
assertThrows 是 org.junit.jupiter.api.Assertions 中的静态方法,语法简洁且类型安全:
- 第一个参数是期望抛出的异常类(如
IllegalArgumentException.class) - 第二个参数是函数式接口
Executable,传入一个 lambda 表达式或方法引用,表示要执行并触发异常的代码 - 方法返回捕获到的异常实例,可用于后续断言(例如验证异常消息)
示例:
@Test
void testDivideByZero() {
ArithmeticException exception = assertThrows(ArithmeticException.class, () -> {
int result = 10 / 0; // 这里会抛出 ArithmeticException
});
assertEquals("/ by zero", exception.getMessage());
}
验证异常消息或属性(推荐组合使用)
仅检查异常类型不够严谨,实际中常需确认异常消息是否符合预期。由于 assertThrows 返回异常对象,可链式调用 assertEquals、assertTrue 等进一步校验:
- 用
exception.getMessage()断言提示文本 - 对自定义异常,可断言其字段(如错误码、原因等)
- 避免只写
assertThrows(...)后不处理返回值——那样等于没验证消息
示例(含自定义异常):
class ValidationException extends RuntimeException {
private final int errorCode;
ValidationException(String msg, int code) {
super(msg);
this.errorCode = code;
}
int getErrorCode() { return errorCode; }
}
@Test
void testValidateNameTooShort() {
ValidationException e = assertThrows(ValidationException.class, () ->
validateName("a") // 假设该方法在名字太短时抛出 ValidationException
);
assertEquals("Name too short", e.getMessage());
assertEquals(400, e.getErrorCode());
}
常见误区与注意事项
- 不要在 lambda 外提前调用可能抛异常的方法(否则测试会在执行
assertThrows前就失败) - 确保 lambda 内只包含被测逻辑,避免混入断言或副作用代码
- JUnit 4 没有
assertThrows,强行使用会编译报错;若无法升级,可用@Test(expected = XxxException.class),但无法校验异常消息 - 如果被测方法正常返回(未抛异常),
assertThrows会自动失败并提示 “Expected … to be thrown”
对比 JUnit 4 的替代方案(仅作兼容参考)
若项目仍用 JUnit 4,可用以下方式,但功能较弱:
-
@Test(expected = NullPointerException.class):只能声明预期类型,无法验证消息或状态 -
ExpectedException规则(JUnit 4.12+):已标记为@Deprecated,不推荐新用 - 手动 try-catch:冗长且易出错(比如忘记
fail()导致异常未抛出时测试误通过)
因此,升级到 JUnit 5 并使用 assertThrows 是更清晰、可靠的选择。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











