如何为标注@ControllerAdvice的GlobalExceptionHandler编写Spring Boot测试用例
解决方案
你当前的测试没有命中异常处理方法有两个核心原因,下面给出两种可行的测试方案,以及你原有代码的问题说明。
方案1:单元测试直接验证异常处理逻辑
这种方案不需要启动完整Spring上下文,执行速度快,可以直接覆盖目标方法逻辑:
@RunWith(MockitoJUnitRunner.class) public class GlobalExceptionHandlerControllerTest { @InjectMocks private GlobalExceptionHandlerController exceptionHandler; @Mock private WebRequest webRequest; @Test public void testHandleGenericNotFoundException() { // 构造目标异常 NoHandlerFoundException testException = new NoHandlerFoundException("GET", "/test/not/exist", new HttpHeaders()); // 直接调用异常处理方法 ResponseEntity<CustomErrorResponse> response = exceptionHandler.handleGenericNotFoundException(testException, webRequest); // 校验返回结果 assertEquals(HttpStatus.NOT_FOUND, response.getStatusCode()); CustomErrorResponse body = response.getBody(); assertNotNull(body); assertEquals(HttpStatus.NOT_FOUND.value(), body.getStatus()); assertEquals("NOT_FOUND_ERROR", body.getErrorCode()); assertNotNull(body.getTimestamp()); } }
方案2:集成测试验证全链路生效
如果需要验证全局异常处理器在Spring请求链路中真实生效,可以采用MockMvc做集成测试,需要先做前置配置:
- 先在
application.properties中添加配置,让Spring在找不到请求处理器时抛出对应异常:
# 找不到处理器时抛出NoHandlerFoundException spring.mvc.throw-exception-if-no-handler-found=true # 关闭静态资源映射,避免Spring去静态资源路径匹配不存在的请求 spring.web.resources.add-mappings=false # 低版本SpringBoot使用该配置替代上一条 # spring.resources.add-mappings=false
- 编写集成测试代码:
@SpringBootTest @AutoConfigureMockMvc @RunWith(SpringRunner.class) public class GlobalExceptionHandlerIntegrationTest { @Autowired private MockMvc mockMvc; @Test public void testNoHandlerFoundExceptionHandledCorrectly() throws Exception { mockMvc.perform(MockMvcRequestBuilders.get("/nonexistent/path")) .andExpect(status().isNotFound()) .andExpect(jsonPath("$.status").value(404)) .andExpect(jsonPath("$.errorCode").value("NOT_FOUND_ERROR")) .andExpect(jsonPath("$.message").isNotEmpty()) .andExpect(jsonPath("$.timestamp").isNotEmpty()); } }
原有测试的问题
- 你在测试中主动抛出异常后没有逻辑触发全局异常处理器处理,异常直接被JUnit的
expected规则捕获,根本没有进入你写的handleGenericNotFoundException方法 - 你要处理的异常是
NoHandlerFoundException,但测试中抛出的是NoHandlerMethodFoundException,二者是完全不同的异常类,就算触发异常处理逻辑也不会匹配到你的方法
内容的提问来源于stack exchange,提问作者nongjai
相关产品推荐
相关产品推荐

