spring boot单元测试中需用@autoconfiguremockmvc+@springboottest(webenvironment=mock)启用web环境,通过mockmvc调用触发异常的接口,验证全局异常处理器返回的标准result结构及对应code、message和状态码。

在 Spring Boot 单元测试中模拟全局异常并断言返回结果,关键不是“抛出异常后看控制台”,而是**让请求真实走通 Web 层(含 @RestControllerAdvice)→ 触发全局异常处理器 → 返回标准 Result 结构 → 用 MockMvc 验证响应体和状态码**。整个过程不依赖启动完整容器,但需启用 Web 环境支持。
启用 Web 测试环境与 MockMvc
必须使用 @AutoConfigureMockMvc + @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) 或更轻量的 webEnvironment = SpringBootTest.WebEnvironment.MOCK。后者更常用,它会加载 MVC 上下文但不启动真实 HTTP 服务器。
- 添加
@AutoConfigureMockMvc注解,自动注入MockMvc实例 - 确保全局异常处理器类(如
GlobalExceptionHandler)被 Spring 扫描到(通常放在主启动类同包或子包) - 不用
@WebMvcTest,因为它默认不加载@RestControllerAdvice,需手动@Import,容易遗漏
模拟业务异常并断言 JSON 响应
以自定义 BusinessException(400, "用户名已存在") 为例:先写一个会主动抛出该异常的测试接口(仅用于测试),再用 MockMvc 调用它,验证是否被全局处理器捕获并转成 Result.fail(400, "...")。
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 在测试配置中临时加一个控制器方法(或复用已有接口):
@GetMapping("/test-business-exception")<br>public String triggerBusinessException() {<br> throw new BusinessException(400, "用户名已存在");<br>} - 测试代码中用
mockMvc.perform(get("/test-business-exception"))发起请求 - 用
.andExpect(status().is2xxSuccessful())不对——业务异常应返回 200(因为是正常响应体,非 HTTP 错误);正确断言是:.andExpect(status().isOk())<br>.andExpect(content().contentType(MediaType.APPLICATION_JSON))<br>.andExpect(jsonPath("$.code").value(400))<br>.andExpect(jsonPath("$.message").value("用户名已存在"))
模拟系统级异常(如空指针)并验证兜底处理
这类异常不会被业务层捕获,会直达全局处理器中的 @ExceptionHandler(Exception.class) 方法,应返回统一失败结构(如 code=500)。
- 新增测试接口:
@GetMapping("/test-null-pointer")<br>public String triggerNPE() {<br> String s = null;<br> return s.toString(); // 明确触发 NullPointerException<br>} - 断言重点:
.andExpect(status().isOk())<br>.andExpect(jsonPath("$.code").value(500))<br>.andExpect(jsonPath("$.message").value("服务器异常,请联系管理员"))
注意:不要断言包含堆栈信息的字段,全局处理器里不应把e.printStackTrace()写进 message - 日志可额外验证:用
@SpyBean注入GlobalExceptionHandler,配合verify(...).error(any(), any())检查是否记录了 error 日志
验证参数校验异常(@Valid)是否被拦截
当 Controller 方法参数带 @Valid 且校验失败时,Spring 会抛 MethodArgumentNotValidException,需在全局处理器中专门捕获。
- 写一个带校验的 POST 接口:
@PostMapping("/user")<br>public Result<user> createUser(@Valid @RequestBody User user) { ... }</user> - 用 MockMvc 发送非法 JSON(如 name 为空字符串):
mockMvc.perform(post("/user")<br> .contentType(MediaType.APPLICATION_JSON)<br> .content("{\"name\":\"\",\"age\":25}\")) - 断言返回的错误信息来自校验注解(如
@NotBlank的message),例如:.andExpect(jsonPath("$.message").value("用户名不能为空")) - 确保全局处理器中有对应方法:
@ExceptionHandler(MethodArgumentNotValidException.class)<br>public Result> handleValid(Exception e) { ... }










