JUnit测试中如何避免自动Mock MongoRepository并正常执行调用?
嘿,我来帮你搞定这个问题。首先得揪出根源:你的测试类配置里,@SpringBootApplication(scanBasePackageClasses= {})和@SpringBootTest(classes= {})都传了空数组,这直接导致Spring容器没法扫描到你的MongoRepository接口以及Mongo相关的自动配置类。容器里找不到真实的Repository实例,Spring Boot Test就自动给你生成了一个Mock版本,这就是为啥返回null的原因。
下面给你几个可行的解决方向,你可以根据自己的测试场景选:
1. 让Spring正确扫描到你的Repository和配置类
这是最直接的方案,把空的扫描配置补上:
- 修改
@SpringBootApplication的参数,要么用scanBasePackageClasses传入你Repository所在包的标记类(比如你的MongoRepository是com.yourproject.repo.UserRepository,就传UserRepository.class),要么用scanBasePackages直接指定包路径:@SpringBootApplication(scanBasePackages = {"com.yourproject.repo", "com.yourproject.config"}) - 同时,
@SpringBootTest的classes参数要么直接删掉(让它自动加载你的主启动类),要么明确传入你的主应用类:@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT, classes = YourMainApplication.class)
这样Spring会自动加载Mongo的自动配置,创建真实的Repository实例,不会再生成Mock了。
2. 显式禁用自动Mock,手动注册真实Repository
如果因为某些原因你不想调整扫描范围,也可以手动告诉Spring要使用真实的Repository:
- 在测试类里定义一个内部的
TestConfiguration类,手动创建Repository实例:@TestConfiguration static class TestMongoConfig { @Bean public UserRepository userRepository(MongoTemplate mongoTemplate) { // 这里替换成你的实体类和Repository类型 return new SimpleMongoRepository<>(MongoEntityInformation.of(User.class), mongoTemplate); } } - 然后在测试类上加上
@Import(TestMongoConfig.class),这样Spring容器里就会优先使用你手动注册的真实Repository,而不是生成Mock。
3. 使用嵌入式MongoDB(集成测试推荐)
如果你的测试是集成测试,不想连接真实的生产MongoDB,可以引入嵌入式Mongo依赖,让Spring自动启动一个本地临时Mongo实例,你的Repository会直接操作这个真实的数据库:
- Maven依赖添加:
<dependency> <groupId>de.flapdoodle.embed</groupId> <artifactId>de.flapdoodle.embed.mongo</artifactId> <scope>test</scope> </dependency> - Gradle的话:
testImplementation 'de.flapdoodle.embed:de.flapdoodle.embed.mongo'
Spring Boot会自动配置嵌入式Mongo的连接,你甚至不用改application-local.properties,测试时就能用真实的Repository进行CRUD操作,完全不用Mock。
最后提醒下:如果这是单元测试,其实Mock Repository是常规操作,但你既然要真实调用,那更适合做成集成测试,上面的方案都能满足你的需求。
内容的提问来源于stack exchange,提问作者Faraz Tahir

