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

使用@RestControllerAdvice与@ExceptionHandler后单元测试预期异常不触发问题

实现方案

1. 异常日志记录

直接在全局异常处理类的@ExceptionHandler方法中手动打印异常日志即可,不会影响原有正常的响应返回逻辑:

@RestControllerAdvice
public class GlobalExceptionHandler {
    private static final Logger log = LoggerFactory.getLogger(GlobalExceptionHandler.class);

    @ExceptionHandler(BusinessException.class)
    public ResponseEntity<ErrorResponse> handleBusinessException(BusinessException e) {
        // 最后传入异常对象e即可打印完整堆栈信息,按需调整日志级别和内容
        log.error("业务异常触发,错误码:{},错误描述:{}", e.getErrorCode(), e.getMessage(), e);
        return ResponseEntity.status(HttpStatus.BAD_REQUEST)
                .body(new ErrorResponse(e.getErrorCode(), e.getMessage()));
    }
}

注意:不要在@ExceptionHandler方法中重新抛出捕获的异常,否则会导致异常进入Spring MVC默认处理流程,破坏你原有正常的响应返回逻辑

2. 单元测试适配

根据你的测试场景选择对应方案即可:

2.1 Controller层MockMvc测试(走完整请求链路)

不需要断言异常抛出,直接校验接口返回的状态码、响应体内容是否符合对应异常的配置,就能确认异常确实触发:

@SpringBootTest
@AutoConfigureMockMvc
public class UserControllerTest {
    @Autowired
    private MockMvc mockMvc;

    @Test
    public void testNonExistUserQuery() throws Exception {
        mockMvc.perform(get("/user/10000")) // 该ID对应数据不存在,预期抛用户不存在异常
                .andExpect(status().isBadRequest())
                .andExpect(jsonPath("$.errorCode").value("USER_NOT_FOUND"))
                .andExpect(jsonPath("$.message").value("用户不存在"));
    }
}

2.2 Service层单元测试(只校验业务逻辑)

测试时不要将@RestControllerAdvice修饰的全局异常处理类加载到测试上下文,即可正常断言异常抛出:

// 仅加载所需的Service相关Bean,不引入web层异常处理组件
@SpringBootTest(classes = {UserService.class})
public class UserServiceTest {
    @Autowired
    private UserService userService;

    @Test
    public void testNonExistUserQuery() {
        // 直接断言异常抛出即可
        assertThatThrownBy(() -> userService.getById(10000L))
                .isInstanceOf(BusinessException.class)
                .hasMessage("用户不存在");
    }
}

如果需要批量排除全局异常Handler,可以通过自定义测试配置的扫描过滤规则实现:

@TestConfiguration
@ComponentScan(excludeFilters = {
        @ComponentScan.Filter(type = FilterType.ANNOTATION, value = RestControllerAdvice.class)
})
public class TestExcludeGlobalExceptionConfig {
}

内容的提问来源于stack exchange,提问作者Vahancho22

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 16:09:01