JUnit 5 的 assertThrows() 是最直接、推荐的异常测试方式,既能验证异常类型,又能获取异常对象校验消息、错误码等;支持基础用法(仅类型检查)和进阶用法(消息及字段断言),并可配合 Mockito 模拟依赖异常场景。

用 JUnit 5 的 assertThrows() 是最直接、推荐的方式——它既能确认异常被抛出,又能拿到异常对象做进一步校验,比如消息、错误码等。
基础用法:只验证异常类型
适用于快速确认某段逻辑在非法输入时是否触发了目标异常:
- 第一个参数传入期望的异常类,如
IllegalArgumentException.class - 第二个参数是 lambda 表达式,封装可能抛异常的代码,例如
() -> service.process(null) - 方法执行后若未抛出该异常,测试直接失败
示例:assertThrows(NullPointerException.class, () -> userService.findById(null));
进阶用法:同时校验异常消息和字段
业务中常需确保提示文案或自定义属性准确,不能只看类型:
立即学习“Java免费学习笔记(深入)”;
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 把
assertThrows()返回值赋给变量,避免重复执行 - 用
assertEquals()断言e.getMessage()是否匹配预期文本 - 若为自定义异常(如
BusinessException),可直接调用e.getErrorCode()等 getter 方法断言
示例:
BusinessException e = assertThrows(BusinessException.class, () -> orderService.submit(new Order(null)));<br>assertEquals("ERR_ORDER_EMPTY", e.getErrorCode());<br>assertEquals("订单不能为空", e.getMessage());
配合 Mockito 模拟异常触发场景
当异常来自依赖服务(如数据库、远程调用),需先 mock 出错行为:
- 对 void 方法,必须用
doThrow(...).when(mock).method(),不能用when().thenThrow() - 对有返回值的方法,两种写法都可,但
doThrow()更统一、更安全 - 模拟后调用被测方法,再用
assertThrows()验证最终抛出的是否为上层包装后的异常
示例:
doThrow(new SQLException("Connection refused")).when(dataSource).getConnection();<br>assertThrows(DataAccessException.class, () -> userService.loadAll());
注意几个易错点
有些细节不注意会导致误判或空指针:
-
assertThrows已保证返回非 null 异常对象,但若后续链式调用e.getMessage().contains(...),仍建议先断言e.getMessage()不为 null(尤其在自定义逻辑中) - 确保被测代码确实走到了抛异常的分支,比如 if 条件、状态判断、mock 打桩是否生效
- JUnit 4 的
@Test(expected = ...)不推荐:无法获取异常实例,也无法控制抛出位置

















