Mock测试控制器时异常未触发,返回code始终为SUCCESS问题排查
以下是针对你的问题的具体排查步骤:
确认全局异常处理器被测试上下文加载
控制器测试(比如用@WebMvcTest)默认只会加载控制器相关的Bean,全局异常处理器如果不在扫描范围内,不会被自动加载。可以在测试类上添加@Import(GlobalExceptionHandler.class),或者确保@SpringBootTest覆盖了异常处理器所在的包路径。检查控制器是否吞掉了异常
查看控制器中调用用例方法的代码,是否存在try-catch块意外捕获了InvalidInputException并返回了SUCCESS结果。比如:// 错误示例:异常被吞掉 @PostMapping("/auth/signup/checkDuplicated") public ResponseEntity<Result> checkDuplicate(@RequestBody SignupRequest req) { try { signupService.execute(convertToCommand(req)); return ResponseEntity.ok(Result.success()); } catch (Exception e) { // 这里错误地返回了SUCCESS,而不是让全局处理器处理 return ResponseEntity.ok(Result.success()); } }确保控制器没有手动捕获该异常,让异常自然抛出给全局处理器处理。
验证Mock的匹配逻辑是否正确
检查测试中findByEmail的Mock设置,是否与请求中的邮箱完全匹配。比如测试时设置的是when(userRepo.findByEmail("test@test.com")).thenReturn(Optional.of(user)),但实际请求的邮箱是test@example.com,会导致Mock不生效,用例不会抛出异常。可以用anyString()临时测试,确认Mock是否能触发异常:when(userRepo.findByEmail(anyString())).thenReturn(Optional.of(new User()));确认全局异常处理器的逻辑正确性
检查@RestControllerAdvice注解的异常处理器,是否正确处理了InvalidInputException:@RestControllerAdvice public class GlobalExceptionHandler { @ExceptionHandler(InvalidInputException.class) public ResponseEntity<Result> handleInvalidInput(InvalidInputException ex) { // 确保返回的Result对象的code是ERROR,且HTTP状态码正确(比如400) return ResponseEntity.badRequest().body(Result.error(ex.getMessage())); } }同时确认该类被Spring正确扫描(比如包路径在
@SpringBootApplication的扫描范围内)。检查控制器测试的断言逻辑
确保测试中正确断言了响应体的code字段,而不是仅检查HTTP状态码。示例:mockMvc.perform(post("/auth/signup/checkDuplicated") .contentType(MediaType.APPLICATION_JSON) .content(objectMapper.writeValueAsString(signupRequest))) .andExpect(status().isBadRequest()) .andExpect(jsonPath("$.code").value("ERROR"));验证用例方法在控制器调用时确实抛出异常
在测试中添加验证逻辑,确认signupService的方法被调用时确实抛出了InvalidInputException:// 验证方法被调用 verify(signupService).execute(any(UserSignupCommand.class)); // 直接调用方法确认抛出异常 assertThrows(InvalidInputException.class, () -> signupService.execute(convertToCommand(signupRequest)));如果这一步断言成功,但接口返回SUCCESS,问题必然出在控制器或全局异常处理器的环节。
内容的提问来源于stack exchange,提问作者강찬욱

