You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为标注@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做集成测试,需要先做前置配置:

  1. 先在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
  1. 编写集成测试代码:
@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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.04 01:57:03