1. 概述
本文将介绍如何结合 Flapdoodle 提供的嵌入式 MongoDB 方案与 Spring Boot,实现流畅的 MongoDB 集成测试。
✅ MongoDB 是当前最流行的 NoSQL 文档型数据库之一。凭借出色的可扩展性、原生支持分片机制以及活跃的社区生态,它被许多开发者视为“首选 NoSQL 存储”。
与任何持久化技术一样,能否轻松地对数据库与应用其他模块的集成进行测试,至关重要。幸运的是,Spring Boot 为这类测试提供了非常友好的支持,配合嵌入式数据库,可以做到开箱即用。
2. Maven 依赖
首先,我们为 Spring Boot 项目配置 Maven 父工程。使用 spring-boot-starter-parent
后,无需手动为每个依赖声明版本号,简化依赖管理。
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.2.0</version>
<relativePath /> <!-- 从仓库解析父级 POM -->
</parent>
接着引入核心依赖:
Spring Data MongoDB 支持
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-mongodb</artifactId> </dependency>
嵌入式 MongoDB(仅测试环境使用)
<dependency> <groupId>de.flapdoodle.embed</groupId> <artifactId>de.flapdoodle.embed.mongo</artifactId> <scope>test</scope> </dependency>
⚠️ 注意:
de.flapdoodle.embed.mongo
仅用于测试,通过<scope>test</scope>
限制其作用范围,上线时不会引入该依赖,无需额外关闭嵌入式数据库。
3. 使用嵌入式 MongoDB 进行测试
本节涵盖两种常见场景:Spring Boot 自动配置测试 和 手动配置测试。
3.1. Spring Boot 测试(推荐)
添加 de.flapdoodle.embed.mongo
后,Spring Boot 会在运行测试时自动下载并启动嵌入式 MongoDB 实例。首次下载较慢,后续测试会复用本地实例,速度飞快。
以下是一个典型的 JUnit 5 集成测试示例:
@DataMongoTest
@ExtendWith(SpringExtension.class)
public class MongoDbSpringIntegrationTest {
@DisplayName("给定对象,使用 MongoDB Template 保存,应成功存储")
@Test
public void test(@Autowired MongoTemplate mongoTemplate) {
// given
DBObject objectToSave = BasicDBObjectBuilder.start()
.add("key", "value")
.get();
// when
mongoTemplate.save(objectToSave, "collection");
// then
assertThat(mongoTemplate.findAll(DBObject.class, "collection"))
.extracting("key")
.containsOnly("value");
}
}
✅ 效果:测试运行时,Spring 自动拉起嵌入式 MongoDB,控制台会输出类似:
...Starting MongoDbSpringIntegrationTest on localhost with PID 12345...
整个过程无需任何额外配置,简单粗暴,适合大多数场景。
3.2. 手动配置测试(高级用法)
虽然 Spring Boot 能自动配置,但某些情况下我们可能需要手动控制嵌入式 MongoDB 的版本、端口或网络配置,比如验证特定 MongoDB 版本的行为。
以下代码展示了如何手动启动嵌入式实例,并创建 MongoTemplate
:
class ManualEmbeddedMongoDbIntegrationTest {
private static final String CONNECTION_STRING = "mongodb://%s:%d";
private MongodExecutable mongodExecutable;
private MongoTemplate mongoTemplate;
@AfterEach
void clean() {
mongodExecutable.stop();
}
@BeforeEach
void setup() throws Exception {
String ip = "localhost";
int port = 27017;
ImmutableMongodConfig mongodConfig = MongodConfig
.builder()
.version(Version.Main.PRODUCTION) // 使用生产版本
.net(new Net(ip, port, Network.localhostIsIPv6()))
.build();
MongodStarter starter = MongodStarter.getDefaultInstance();
mongodExecutable = starter.prepare(mongodConfig);
mongodExecutable.start();
mongoTemplate = new MongoTemplate(
MongoClients.create(String.format(CONNECTION_STRING, ip, port)),
"test"
);
}
@DisplayName("给定对象,使用 MongoDB Template 保存,应成功存储")
@Test
void test() {
// given
DBObject objectToSave = BasicDBObjectBuilder.start()
.add("key", "value")
.get();
// when
mongoTemplate.save(objectToSave, "collection");
// then
assertThat(mongoTemplate.findAll(DBObject.class, "collection"))
.extracting("key")
.containsOnly("value");
}
}
📌 技巧:若想将手动创建的 MongoTemplate
注入 Spring 容器,可使用 @TestConfiguration
定义一个 @Bean
方法返回该实例,便于在多个测试中复用。
更多配置细节可参考 Flapdoodle 官方 GitHub 仓库。
3.3. 日志控制
集成测试时,MongoDB 的日志可能会刷屏。可通过在 src/test/resources/application.properties
中调整日志级别来控制:
# 控制嵌入式 MongoDB 相关日志
logging.level.org.springframework.boot.autoconfigure.mongo.embedded=off
logging.level.org.mongodb=off
✅ 推荐测试时关闭这些日志,避免干扰输出。需要调试时再打开 DEBUG
级别。
3.4. 生产环境使用真实数据库
由于 de.flapdoodle.embed.mongo
被声明为 test
范围依赖,在生产环境中天然不会生效,无需额外配置开关。
只需在 application.yml
中指定真实 MongoDB 的连接信息即可:
spring:
data:
mongodb:
uri: mongodb://prod-mongo-host:27017/myapp
📌 进阶建议:若想在不同环境(如本地开发、CI)灵活切换嵌入式与真实数据库,可使用 Spring Profile 配置不同的 MongoClient
Bean,实现无缝切换。
例如:
@Profile("test")
:使用嵌入式 MongoDB@Profile("prod")
:使用远程 MongoDB 实例
同时,生产环境的 MongoDB 驱动依赖应设置为 <scope>runtime</scope>
,确保测试时不冲突。
4. 嵌入式测试的争议
嵌入式数据库看似完美,但也有明显局限。
✅ 适合场景:
- 验证实体与文档的映射(如
@Document
注解行为) - 测试自定义持久化事件监听器(如继承
AbstractMongoEventListener
) - 验证直接操作持久层的业务逻辑
❌ 不适合场景:
- 不能替代“全链路集成测试”。Flapdoodle 的嵌入式 MongoDB 并非官方 MongoDB 二进制,行为可能与生产环境存在细微差异。
- 无法测试真实网络延迟、连接池行为、分片集群、副本集选举等高级特性。
📌 推荐方案:若需更贴近生产环境的测试,建议使用 Docker 启动真实 MongoDB 容器。通过 Testcontainers
等工具,可在 CI/CD 中动态管理容器生命周期,实现真正的端到端集成测试。
想了解 Docker 化 Spring Boot 应用?可参考我们之前的教程:《Dockerizing a Spring Boot Application》
5. 总结
Spring Boot 配合 Flapdoodle,让 MongoDB 集成测试变得极其简单。只需添加一个依赖,即可自动获得嵌入式数据库支持,快速验证数据层逻辑。
但务必记住:
⚠️ 嵌入式 MongoDB ≠ 生产级 MongoDB
它适合单元化、模块化的集成验证,但不能替代基于真实环境的集成测试。合理使用嵌入式数据库,结合 Docker 容器化方案,才能构建真正可靠的测试体系。
本文所有示例代码已托管至 GitHub:
👉 https://github.com/eugenp/tutorials/tree/master/persistence-modules/spring-boot-persistence-mongodb