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

Spring REST API测试:Mockito thenThrow()后代码不执行问题求助

问题分析与解决方案

我来帮你梳理下这个测试用例里的几个关键问题,一步步拆解清楚:

1. Mock对象未正确注入,导致真实方法被执行

你提到已经Mock了BookService,但从测试代码来看,大概率是Mock对象没有正确注入到BookController中,或者bookService本身不是一个有效的Mock实例。

当你执行when(bookService.findBookByName(any())).thenThrow(new Exception())时,如果bookService是真实对象而非Mock对象,这行代码会直接调用真实的findBookByName方法——如果这个真实方法抛出了异常,就会直接触发测试用例的expected = Exception.class条件,导致后续的System.out.println("hello2")和控制器调用代码都不会执行,测试直接“通过”。

解决方法:

确保测试类中正确配置Mockito的注解,让Mock对象被自动注入到控制器里:

@RunWith(MockitoJUnitRunner.class) // JUnit 4用这个,JUnit 5用MockitoExtension
public class BookControllerTest {
    @Mock
    private BookService bookService; // 声明Mock对象

    @InjectMocks
    private BookController bookController; // 自动将Mock注入到控制器中

    // 你的测试方法...
}

2. 测试用例期望的异常类型不匹配

看你的控制器代码:

try {
    Books resultBooks = bookService.findBookByName(bookName);
    // ...
} catch(Exception e){
    throw new RuntimeException(); // 这里抛出的是RuntimeException,不是原始的Exception
}

当bookService抛出Exception时,控制器会捕获它并重新抛出RuntimeException,但你的测试用例标注的是@Test(expected = Exception.class)——这会导致测试实际抛出的异常和期望的不一致,原本应该失败,但因为前面的Mock问题导致真实方法抛出了Exception,才让测试“巧合”通过。

解决方法:

把测试用例的期望异常改成RuntimeException.class:

@Test(expected = RuntimeException.class)
public void getBookDetails_shouldReturn500() throws Exception {
    // ...
}

3. 断言代码永远不会执行

因为测试用例标注了expected = Exception.class,一旦抛出对应异常,测试框架会直接终止测试流程,后面的responseEntity获取和断言代码根本不会运行——这就是为什么不管你断言is2xxSuccessful还是is5xxServerError,测试都能通过的原因,因为断言根本没执行。

解决方法:

如果你想验证控制器抛出异常后的HTTP状态码,建议用MockMvc来模拟HTTP请求,而不是直接调用控制器方法。这样可以完整测试请求处理流程:

@Test
public void getBookDetails_shouldReturn500() throws Exception {
    String bookName = "First";
    when(bookService.findBookByName(any())).thenThrow(new Exception());

    mockMvc.perform(get("/books/getDetails/{bookName}", bookName))
           .andExpect(status().isInternalServerError()); // 验证500状态码
}

使用MockMvc需要在测试类中配置:

@Autowired
private MockMvc mockMvc;

// 或者在@Before方法中手动初始化
@Before
public void setup() {
    mockMvc = MockMvcBuilders.standaloneSetup(bookController).build();
}

总结

现在的测试用例因为Mock注入问题,导致真实方法被调用,加上异常类型不匹配、断言未执行,才出现了你看到的奇怪现象。按照上面的步骤修正Mock配置、调整异常期望、改用MockMvc测试HTTP请求,就能得到正确的测试结果了。

内容的提问来源于stack exchange,提问作者Rishabh Sharma

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 09:07:26