如何为无参数且调用MongoTemplate查询的方法编写单元测试
单元测试报错解决及正确写法
错误原因
- 断言逻辑错误:你构造的
expected列表中存入的是Mockito生成的MyInventory代理对象,而给mongoTemplate.find打桩返回的是通过Builder构造的真实MyInventory实例,两类对象的属性、哈希值完全不同,直接断言必然失败。 - 未覆盖目标业务逻辑:测试中没有注入待测试的
MyInventoryService实例,也没有调用getAllData()方法,完全没有验证业务逻辑的正确性,测试无效。 - 注解配置冗余:同时混用了JUnit4的
@RunWith(SpringRunner.class)和JUnit5的@ExtendWith(MockitoExtension.class),配置不合理,容易引发上下文加载问题。
修正方案
步骤1:简化测试配置,注入待测试服务
如果使用SpringBoot 2.2+自带的JUnit5环境,不需要混用注解,直接通过@MockBean替换容器中的MongoTemplate,注入待测试的Service即可。
步骤2:对齐期望结果与实际返回的对象类型
不要使用Mockito mock实体类,直接用你构造的真实MyInventory实例作为期望结果。
步骤3:补充Query参数校验(可选)
如果需要验证getAllData内部生成的查询条件是否正确,可以捕获mongoTemplate.find收到的Query参数,校验Criteria规则是否符合预期。
修正后的测试代码
@ExtendWith(SpringExtension.class) @SpringBootTest @ActiveProfiles("mock") public class MyInventoryServiceTest { // 注入待测试的业务服务 @Autowired private MyInventoryService myInventoryService; // 替换容器中的MongoTemplate为Mock对象 @MockBean private MongoTemplate mongoTemplate; @Test public void testGetAllData() { // 构造mock返回的测试数据 List<MyInventory> mockMyInventoryList = new ArrayList<>(); mockMyInventoryList.add(MyInventory.builder() .id("614a4d70cghyt86") .it_key("DESS") // 补充其他需要的属性 .build() ); // 给MongoTemplate的find方法打桩 when(mongoTemplate.find(any(Query.class), eq(MyInventory.class))) .thenReturn(mockMyInventoryList); // 调用待测试的业务方法 List<MyInventory> actualResult = myInventoryService.getAllData(); // 断言返回结果和预期一致 assertEquals(mockMyInventoryList, actualResult); // 可选:校验Query的查询条件是否符合预期 ArgumentCaptor<Query> queryCaptor = ArgumentCaptor.forClass(Query.class); verify(mongoTemplate, times(1)).find(queryCaptor.capture(), eq(MyInventory.class)); Query capturedQuery = queryCaptor.getValue(); // 这里可以写逻辑校验capturedQuery里的Criteria是否正确 // 比如校验是否包含对应字段的查询条件 } }
额外注意
你原实体类的Lombok注解存在拼写错误:@NoAgrsConstructor应为@NoArgsConstructor,请修正避免编译报错。
内容的提问来源于stack exchange,提问作者Jeet
相关产品推荐
相关产品推荐

