邮件发送失败测试返回HTTP 200而非500问题排查
问题分析与解决方案
核心原因1:Mockito参数匹配器不匹配null值
你的测试中使用anyList()作为参数匹配器,但Mockito的anyList()默认不匹配null值——而控制器传入的ccEmails和bccEmails是null(测试用例未设置这两个字段)。这导致你配置的doThrow逻辑未被触发,emailOperations.sendBasicEmail()方法没有抛出异常,控制器正常执行并返回200。
修复方法
将mock中的anyList()替换为支持null的匹配器:
- 若使用Mockito 4.6+,可用
anyList().nullable() - 通用兼容写法:用
any()或nullable(List.class)
修改后的mock代码:
doThrow(new EmailSendingException("Failed to send email")).when(emailOperations) .sendBasicEmail(anyString(), nullable(List.class), nullable(List.class), anyString(), anyString(), anyBoolean());
核心原因2:测试断言与异常处理器返回格式不匹配
你的测试断言期望返回字符串"Failed to send email. Please try again later.",但异常处理器实际返回的是ErrorResponse对象的JSON结构。即使异常被正确抛出,这个断言也会失败。
修复方法
改用JSON断言验证响应内容:
.andExpect(status().isInternalServerError()) .andExpect(jsonPath("$.code").value("EMAIL_SENDING_FAILED")) .andExpect(jsonPath("$.message").value("Failed to send email"));
注:需确保测试类引入了Spring MVC的JSON断言支持(@SpringBootTest或@WebMvcTest会自动包含)。
额外检查:异常处理器是否正确注册
确认异常处理器类上添加了@RestControllerAdvice(或@ControllerAdvice)注解,否则Spring无法识别该全局异常处理逻辑:
@RestControllerAdvice public class GlobalExceptionHandler { @ExceptionHandler(EmailSendingException.class) public ResponseEntity<ErrorResponse> handleEmailSendingException(EmailSendingException ex) { logger.error("Email sending failed: {}", ex.getMessage(), ex); ErrorResponse errorResponse = new ErrorResponse("EMAIL_SENDING_FAILED", ex.getMessage()); return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(errorResponse); } }
修改后的完整测试用例
@Test @WithMockUser(username = "admin", roles = {"ADMIN"}) void testSendBasicEmail_Failure() throws Exception { // Arrange BasicEmailRequest request = new BasicEmailRequest(); request.setToEmail("test@example.com"); request.setSubject("Test Subject"); request.setBody("Test Body"); request.setIsHtml(false); doThrow(new EmailSendingException("Failed to send email")).when(emailOperations) .sendBasicEmail(anyString(), nullable(List.class), nullable(List.class), anyString(), anyString(), anyBoolean()); // Act & Assert mockMvc.perform(post("/api/email/sendBasic") .with(csrf()) .contentType(MediaType.APPLICATION_JSON) .content(objectMapper.writeValueAsString(request))) .andExpect(status().isInternalServerError()) .andExpect(jsonPath("$.code").value("EMAIL_SENDING_FAILED")) .andExpect(jsonPath("$.message").value("Failed to send email")); verify(emailOperations, times(1)).sendBasicEmail( "test@example.com", null, null, "Test Subject", "Test Body", false); }
内容的提问来源于stack exchange,提问作者Vasco Oliveira
相关产品推荐
相关产品推荐

