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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 02:30:05