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

如何测试应用抛出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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 11:50:24