Spring RestController单元测试中Service层Mock部分方法不生效问题求助
问题排查及解决方案
原因1:ServiceOrder的completedOrdersInPeriod方法是final修饰的
Mockito默认不支持mock final方法,所以你对该方法的桩设定不会生效,调用时会执行真实的业务逻辑,最终抛出异常导致500。
解决方法:
- 去掉ServiceOrder中
completedOrdersInPeriod方法的final修饰符 - 如果不能修改源码,可开启Mockito对final方法的mock支持:
在src/test/resources/META-INF/mockito-extensions目录下创建名为org.mockito.plugins.MockMaker的文件,写入内容:
mock-maker-inline
原因2:参数匹配器使用不当
你在桩设定时用的是无类型的any()匹配器,如果ServiceOrder中存在同名的重载方法,Mockito可能无法正确匹配到completedOrdersInPeriod(LocalDate, LocalDate)这个签名的方法,导致桩设定失效。
解决方法:
将测试类中对应的桩设定改为指定类型的匹配器:
Mockito.when(serviceOrder.completedOrdersInPeriod(any(LocalDate.class), any(LocalDate.class))).thenReturn(1L);
注意要导入org.mockito.ArgumentMatchers.any的包。
原因3:容器内存在多个ServiceOrder实例
如果你的测试配置没有排除项目中实际的ServiceOrder实现类的扫描,Spring容器中会同时存在你mock的ServiceOrder和真实的ServiceOrder两个Bean,可能出现Controller注入的是真实实例,而测试类注入的是mock实例的情况,导致你桩设定的mock对象和实际使用的不是同一个。
解决方法:
在测试配置类上添加@ComponentScan注解,排除真实Service所在的包,避免加载真实Bean:
@ComponentScan(excludeFilters = @ComponentScan.Filter(type = FilterType.REGEX, pattern = "com.your.package.service.*"))
快速定位技巧
你可以在测试方法中添加打印响应详情的逻辑,直接查看500错误的具体异常栈:
mockMvc.perform(MockMvcRequestBuilders.post("/orders/completed/period?start=2020-01-01&end=2022-01-01")) .andDo(MockMvcResultHandlers.print()) // 打印完整请求响应信息 .andExpect(MockMvcResultMatchers.status().isOk());
通过输出的异常信息可以直接定位到具体报错的代码位置。
内容的提问来源于stack exchange,提问作者Anton
相关产品推荐
相关产品推荐

