Spring Boot控制器异常测试问题:Mock异常未被正确捕获返回200
问题分析与解决方案
核心问题排查
1. 异常类型不匹配
测试用例中抛出的是CustomNotFoundException,但你的@RestControllerAdvice只处理CarNotFoundException,两者完全不匹配,这是异常未被捕获的直接原因。
2. 请求路径不匹配
控制器的GetMapping路径是/cars/{id},但测试请求的是/api/cars/98776,路径前缀/api未在控制器中定义,导致请求没命中目标接口,无法触发后续异常逻辑。
3. Mock条件不匹配
测试中Mock的是service.getCar(CONSTANT.CAR_ID),但实际请求的路径参数是98776,如果CONSTANT.CAR_ID不等于"98776",Mock的抛出异常逻辑不会生效,接口会返回默认200(Mock默认返回null,ResponseEntity.ok(null)依然是200状态)。
4. 上下文配置冗余
@WebMvcTest已自动加载控制器、异常处理器等Web层组件,额外添加@ContextConfiguration(classes={MyApplication.class})会加载整个应用上下文,可能导致组件扫描异常,覆盖@WebMvcTest的默认配置。
修正后的代码示例
修正测试用例
@WebMvcTest(MyController.class) // 移除冗余的@ContextConfiguration,仅加载Web层组件 public class ControllerTest { @Autowired private MockMvc mockMvc; @MockBean private Service service; private static final String TEST_CAR_ID = "98776"; @Test void should_return_404_not_found() throws Exception { // 确保Mock参数与请求路径参数一致 when(this.service.getCar(TEST_CAR_ID)) // 抛出与异常处理器匹配的异常类型 .thenThrow(new CarNotFoundException("not Found")); // 请求路径匹配控制器定义的路径 mockMvc.perform(get("/cars/{id}", TEST_CAR_ID) .contentType(MediaType.APPLICATION_JSON)) .andExpect(status().isNotFound()); } }
若需/api前缀,修正控制器路径
如果应用确实需要/api前缀,在控制器类上添加@RequestMapping("/api"):
@RestController @RequestMapping("/api") public class MyController { private final Service service; @GetMapping(value = "/cars/{id}", produces = MediaType.APPLICATION_JSON_VALUE) public ResponseEntity<List<Cars>> getCar(@PathVariable final String carId) { var car = this.service.getCar(carId); return ResponseEntity.ok(car); } }
确保异常处理器被扫描
若Mapper类未被自动扫描,可在@WebMvcTest中显式指定包含该类:
@WebMvcTest( controllers = MyController.class, includeFilters = @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = Mapper.class) ) public class ControllerTest { // ... 测试代码 }
验证步骤
- 确认Mock参数与请求参数完全一致
- 确认抛出的异常类型与
@ExceptionHandler处理的类型匹配 - 检查请求路径与控制器路径一致
- 确保异常处理器类被Spring上下文正确加载
内容的提问来源于stack exchange,提问作者user1555190
相关产品推荐
相关产品推荐

