Java Spring环境下使用Mockito无法Mock MongoDB服务该如何解决?
问题解决方案
根因说明
你当前的问题是混淆了Mockito Mock对象的行为与真实MongoDB访问逻辑:
用@Mock修饰的ShopRepository是Mockito生成的空代理对象,没有任何默认实现,所有方法默认返回null、空集合或基础类型默认值,不会触发任何真实的数据库操作,因此无论怎么配置MongoDB都不会生效。同时你测试类里的ShopRepository变量名首字母大写,和服务类里的shopRepository属性名不匹配,可能导致@InjectMocks注入失败。
方案1:基于Mockito的纯单元测试(无需启动MongoDB)
适合只验证服务层逻辑正确性,不需要真实执行DAO层操作的场景,核心是给Mock对象的方法手动打桩定义返回值:
@RunWith(MockitoJUnitRunner.class) public class GetShopServiceTest { // 变量名和服务类的依赖名保持一致,小写开头 @Mock private ShopRepository shopRepository; @InjectMocks private ShopServiceImpl shopService; @Test public void testSaveAndListShops() { // 1. 构造测试数据 Shop mockShop = new Shop(); mockShop.setId("123"); mockShop.setName("测试店铺"); List<Shop> mockShopList = Collections.singletonList(mockShop); // 2. 给Mock的Repository方法打桩,定义调用时的返回值 when(shopRepository.save(any(Shop.class))).thenReturn(mockShop); when(shopRepository.findAll()).thenReturn(mockShopList); // 3. 调用服务方法 Shop shopSaved = shopService.save(mockShop); List<Shop> shopsRetrieved = shopService.listShops(); // 4. 断言结果符合预期 assertEquals(mockShop.getId(), shopSaved.getId()); assertEquals(1, shopsRetrieved.size()); assertEquals(mockShop.getName(), shopsRetrieved.get(0).getName()); // 5. 验证Repository方法被正确调用 verify(shopRepository, times(1)).save(any(Shop.class)); verify(shopRepository, times(1)).findAll(); } }
方案2:使用嵌入式MongoDB做集成测试(模拟真实CRUD行为)
如果需要验证真实的MongoDB操作逻辑,使用Spring Boot提供的@DataMongoTest注解即可自动配置内存级的嵌入式MongoDB实例,不需要自己搭建Mongo服务:
步骤1:确认依赖(Spring Boot项目默认已包含,无需额外引入)
<!-- pom.xml 中确保有以下依赖 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-mongodb</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency>
步骤2:编写集成测试代码
// 去掉Mockito相关注解,改用DataMongoTest自动配置嵌入式Mongo @RunWith(SpringRunner.class) @DataMongoTest public class GetShopServiceTest { // 注入真实的ShopRepository,会自动连接嵌入式Mongo @Autowired private ShopRepository shopRepository; private ShopServiceImpl shopService; // 测试前初始化服务类 @Before public void setUp() { shopService = new ShopServiceImpl(shopRepository); } @Test public void testRealCrud() { // 构造测试数据 Shop shop = new Shop(); shop.setName("真实测试店铺"); // 真实执行保存、查询逻辑 Shop shopSaved = shopService.save(shop); List<Shop> shopsRetrieved = shopService.listShops(); // 断言真实操作结果 assertNotNull(shopSaved.getId()); assertEquals(1, shopsRetrieved.size()); assertEquals("真实测试店铺", shopsRetrieved.get(0).getName()); } }
内容的提问来源于stack exchange,提问作者wanabe-java-programmer
相关产品推荐
相关产品推荐

