全局异常处理器生效的关键是http请求完整走通web层→触发@restcontrolleradvice→返回标准化json响应→被前端准确识别;需用@springboottest(webenvironment = mock)搭配@autoconfiguremockmvc,确保globalexceptionhandler被扫描,通过mockmvc断言状态码、json类型及code/message字段。

要验证全局异常处理器是否真正生效,关键不是看它能不能“捕获异常”,而是看它能否让一次 HTTP 请求完整走通 Web 层 → 触发 @RestControllerAdvice → 返回标准化的 JSON 响应(比如 {"code":400,"message":"xxx"})→ 并被前端或测试断言准确识别。
启用正确的 Web 测试环境
必须使用 Spring Boot 提供的 Web 模拟上下文,否则 @RestControllerAdvice 不会被加载:
- 用
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.MOCK):启动轻量级 MVC 上下文,不启 HTTP 服务器,适合绝大多数异常测试 - 搭配
@AutoConfigureMockMvc:自动注入MockMvc实例,用于发起真实请求并校验响应 - 避免用
@WebMvcTest:它默认不扫描@RestControllerAdvice,需手动@Import(GlobalExceptionHandler.class),容易遗漏 - 确保全局异常处理器类(如
GlobalExceptionHandler)在主启动类的同包或子包下,能被组件扫描到
构造可触发异常的测试接口
不需要改生产代码,临时加一个仅用于测试的 controller 方法即可:
Java项目代码review工具。分析Git变更+完整调用链路上下文,推断业务需求,进行多维度评分和分类汇总,生成完整PRD文档。包含细粒度Java代码审查清单(Null安全、异常处理、Streams、并发、equals/hashCode、资源管理、API设计、性能、MyBatis/ORM、事务边界、SQL/DD...
- 抛业务异常:
@GetMapping("/test-business") public void throwBusiness() { throw new BusinessException(400, "用户名已存在"); } - 抛系统异常:
@GetMapping("/test-npe") public void throwNPE() { String s = null; s.length(); } - 注意:该接口返回类型可以是
void或任意类型,只要抛出异常即可,后续由全局处理器接管
用 MockMvc 断言完整响应结构
重点验证三件事:HTTP 状态码、响应头类型、JSON 字段内容。不要用 status().is5xxServerError() 判断业务异常——它通常返回 200(成功响应体),不是 HTTP 错误:
-
.andExpect(status().isOk()):业务异常一般走正常通道,状态码为 200 -
.andExpect(content().contentType(MediaType.APPLICATION_JSON)):确认返回的是 JSON,不是 HTML 或空白页 -
.andExpect(jsonPath("$.code").value(400))和.andExpect(jsonPath("$.message").value("用户名已存在")):校验全局处理器封装的字段是否符合预期 - 若处理器对
NullPointerException有兜底逻辑(如统一转成 500),就用对应 code 和 message 断言
覆盖不同异常类型做组合验证
单一测试不够,建议按类分组验证,确保每种拦截逻辑都走通:
- 自定义业务异常(
BusinessException):检查是否返回指定 code + message - 参数校验异常(
MethodArgumentNotValidException):配合@Valid注解的 DTO 测试 - 系统级异常(
NullPointerException、ArithmeticException):验证兜底处理是否生效 - 未声明的运行时异常(
RuntimeException):确认是否落入通用@ExceptionHandler(Exception.class)分支










