assertThrows需接收返回的异常实例才能调用getCause()检查根本原因,且getCause()可能为null,须判空后再断言其类型或消息。

在 Java 单元测试中,assertThrows 用于验证某段代码是否抛出了**预期的异常类型**,而 getCause() 则常用于检查该异常的**根本原因(cause)**是否符合预期。两者结合使用,能精准断言“抛出的是什么异常”以及“它是因为哪个底层异常引发的”。
用 assertThrows 捕获并返回异常实例
assertThrows 不仅做断言,还会**返回被抛出的异常对象**,这是后续调用 getCause() 的前提。直接忽略返回值就无法检查 cause。
- ✅ 正确写法(获取异常实例):
IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> {
parseUser("invalid@");
});
- ❌ 错误写法(只做断言,无法链式检查 cause):
assertThrows(IllegalArgumentException.class, () -> {
parseUser("invalid@");
}); // 返回 void,ex 无法定义
对 getCause 做进一步断言
拿到异常实例后,调用 getCause() 获取其内部封装的原始异常(比如 NullPointerException 或 IOException),再用 assertThat、assertEquals 或 assertInstanceOf 等做校验。
- 检查 cause 类型:
IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> {
parseUser(null);
});
assertInstanceOf(NullPointerException.class, ex.getCause());
- 检查 cause 的消息内容(需非 null):
if (ex.getCause() != null) {
assertTrue(ex.getCause().getMessage().contains("email"));
}
- 用 AssertJ 链式断言更清晰(推荐):
IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> parseUser(""));
assertThat(ex.getCause())
.isInstanceOf(NullPointerException.class)
.hasMessageContaining("email");
注意 getCause 可能为 null
不是所有异常都设置了 cause —— 只有通过带 Throwable cause 构造器创建的异常(如 new IllegalArgumentException("msg", cause))才会有非 null 的 cause。直接 throw new IllegalArgumentException("msg") 的 cause 就是 null。
立即学习“Java免费学习笔记(深入)”;
- 务必先判空再调用
getCause().getMessage(),否则可能触发 NPE 导致测试失败而非断言失败 - 若业务逻辑明确会包装异常(如用
new RuntimeException("wrap", original)),才适合断言 cause;否则应优先断言主异常本身的消息或类型
完整示例:验证嵌套异常链
假设方法内部调用了一个可能抛 IOException 的工具类,并被上层包装为 IllegalStateException:
@Test
void whenReadFileFails_thenThrowsIllegalStateWithIoCause() {
IllegalStateException ex = assertThrows(IllegalStateException.class, () -> readFile("missing.txt"));
// 断言主异常
assertThat(ex).hasMessage("Failed to read config file");
// 断言 cause 存在且类型正确
assertThat(ex.getCause())
.isInstanceOf(IOException.class)
.hasMessage("No such file or directory");
}
不复杂但容易忽略:assertThrows 要接住返回值,getCause 要防 null,链式断言让意图更清晰。


















