如何测试应用抛出500内部服务器异常?测试遇问题求助
解决Spring Boot测试中模拟Repository抛出500异常失败的问题
问题场景
要测试应用在出现500错误时的异常处理逻辑,尝试通过模拟DroneRepository.save()方法抛出UnexpectedErrorException,但运行测试时出现Entity must not be null的错误,自定义异常模拟代码未生效。
报错原因
使用@SpyBean时,默认会调用真实的Repository方法。当Controller层传入的Drone对象为null时,JPA原生的save()方法会先执行非空校验,抛出IllegalArgumentException,导致自定义的异常模拟逻辑根本没机会执行。
另外,测试代码存在语法错误:.andExpect(status().isInternalServerError())末尾缺少闭合括号,会导致编译或运行报错。
解决方法
方案1:改用@MockBean替代@SpyBean
@MockBean是完全模拟对象,不会调用真实的Repository方法,能确保异常模拟逻辑优先执行。
修改测试类中的Repository注入:
@MockBean // 替换原来的@SpyBean private DroneRepository droneRepository;
模拟异常的代码保持不变:
when(droneRepository.save(any(Drone.class))).thenThrow(new UnexpectedErrorException());
方案2:使用doThrow()语法配合@SpyBean
如果必须保留@SpyBean(比如需要复用真实对象的部分逻辑),需使用doThrow()语法跳过真实方法的执行:
// 替换原来的when().thenThrow() doThrow(new UnexpectedErrorException()).when(droneRepository).save(any(Drone.class));
修复测试代码的语法错误
修正mockMvc链式调用中的括号问题:
mockMvc .perform(post("/v1/drone").contentType(MediaType.APPLICATION_JSON) .content(new ObjectMapper().writeValueAsString(newDroneDto))) .andExpect(content().contentType(MediaType.APPLICATION_JSON)) .andExpect(status().isInternalServerError()) // 补充闭合括号 .andExpect(jsonPath("$.error").value("Unexpected Error."));
完整修改后的测试类示例
@SpringBootTest @AutoConfigureMockMvc @TestMethodOrder(MethodOrderer.OrderAnnotation.class) class DronefeederApplicationTests { @Autowired private MockMvc mockMvc; @MockBean // 改用MockBean private DroneRepository droneRepository; @Captor private ArgumentCaptor<Drone> droneCaptor; @BeforeEach public void setup() { // MockBean无需调用真实的deleteAll,可注释或留空 // droneRepository.deleteAll(); } @WithMockUser(username = "dronefeeder") @Test @Order(1) @DisplayName("1 - Should return 500 when saving drone fails unexpectedly") void saveDroneInternalServerErrorTest() throws Exception { DroneDto newDroneDto = new DroneDto(); when(droneRepository.save(any(Drone.class))).thenThrow(new UnexpectedErrorException()); mockMvc .perform(post("/v1/drone").contentType(MediaType.APPLICATION_JSON) .content(new ObjectMapper().writeValueAsString(newDroneDto))) .andExpect(content().contentType(MediaType.APPLICATION_JSON)) .andExpect(status().isInternalServerError()) .andExpect(jsonPath("$.error").value("Unexpected Error.")); } }
内容的提问来源于stack exchange,提问作者Jossany Moura
相关产品推荐
相关产品推荐

