对于 AI 代理:可在 https://www.mongodb.com/zh-cn/docs/llms.txt 获取文档索引—通过在任何 URL 路径后添加 .md 可获取所有页面的 Markdown 版本。

使用测试容器对Java和MongoDB进行集成测试

Testcontainers 是一个Java库,它使用Docker容器来简化集成测试。它会创建在测试期间运行的临时数据库实例,并在测试完成时自动将其删除。

本教程向您展示如何在标准Java和 Spring Boot 应用程序中将测试容器与MongoDB结合使用。

集成测试检查应用程序的不同部分如何协同工作。与验证单段代码的单元测试不同,集成测试会验证您的代码是否能与数据库或 API 等外部系统正确交互。

Testcontainers 在运行测试时执行以下步骤:

  1. 测试之前:创建容器、加载数据库并创建集合

  2. 测试期间:运行测试代码

  3. 测试后:删除容器并释放资源

使用测试容器的测试在任何计算机和任何操作系统上都以相同的方式运行,并且每个测试都使用自己的数据库实例。还可以根据需要在不同数据库版本之间进行切换。

开始之前,请安装以下内容:

您还必须将以下依赖项添加到应用程序的 pom.xml文件中:

<dependencyManagement> <dependencies> <!-- MongoDB Java Driver BOM --> <dependency> <groupId>org.mongodb</groupId> <artifactId>mongodb-driver-bom</artifactId> <type>pom</type> <scope>import</scope> </dependency> <!-- Testcontainers BOM --> <dependency> <groupId>org.testcontainers</groupId> <artifactId>testcontainers-bom</artifactId> <type>pom</type> <scope>import</scope> </dependency> <!-- JUnit BOM --> <dependency> <groupId>org.junit</groupId> <artifactId>junit-bom</artifactId> <type>pom</type> <scope>import</scope> </dependency> </dependencies></dependencyManagement>

以下示例测试查找 IMDb 评级高于 7.0 的电影的查询。要查看完整代码,请参阅 GitHub 存储库。

1

以下代码创建一个MongoDB容器。@Container 注解会在测试前启动容器,并在测试完成后停止容器:

@Containerprivate static final MongoDBContainer mongoDBContainer = new MongoDBContainer("mongo:7.0.0");
2

以下代码连接到容器并添加示例电影:

@BeforeAllpublic void setup() { String uri = mongoDBContainer.getConnectionString(); mongoClient = MongoClients.create(uri); database = mongoClient.getDatabase("testdb"); collection = database.getCollection("testCollection"); // Insert sample data Document doc1 = new Document("title", "Inception").append("imdb", new Document("rating", 8.8)); Document doc2 = new Document("title", "The Room").append("imdb", new Document("rating", 3.7)); Document doc3 = new Document("title", "The Dark Knight").append("imdb", new Document("rating", 9.0)); collection.insertMany(List.of(doc1, doc2, doc3));}
3

以下代码对 imdb.rating字段值大于 7 的电影运行查询并检查结果:

@Testvoid testMoviesWithHighRating() { List<Document> resultDocuments = new ArrayList<>(); try (MongoCursor<Document> cursor = collection.find(Filters.gt("imdb.rating", 7)) .projection(new Document("title", 1).append("_id", 0)) .iterator()) { while (cursor.hasNext()) { Document doc = cursor.next(); System.out.println(doc.toJson()); resultDocuments.add(doc); } } assertEquals(2, resultDocuments.size()); for (Document doc : resultDocuments) { assertTrue(doc.containsKey("title")); assertFalse(doc.containsKey("_id")); }}

此测试验证以下内容:

  • 查询正好返回 2 个文档

  • 每个文档都有一个 title字段

  • 每个文档均不包含 _id字段

以下示例使用Spring Boot MongoDB聚合存储库中的代码来测试 findAll() 方法。

1

以下代码创建一个MongoDB容器:

@Containerpublic static MongoDBContainer mongoDBContainer = new MongoDBContainer(DockerImageName.parse("mongo:7.0.0"));
2

以下代码将 Spring Boot 配置为使用测试数据库:

@DynamicPropertySourcestatic void setProperties(DynamicPropertyRegistry registry) { registry.add("spring.data.mongodb.uri", mongoDBContainer::getReplicaSetUrl); registry.add("spring.data.mongodb.database", () -> "testdb");} @BeforeAllpublic static void setUpAll() { String mongoUri = mongoDBContainer.getConnectionString(); mongoClient = MongoClients.create(mongoUri);} @BeforeEachpublic void setUp() { salesRepository.save(createMockSales());} private Sales createMockSales() { Item item1 = new Item("Item1", Arrays.asList("Tag1", "Tag2"), new BigDecimal("19.99"), 2); Item item2 = new Item("Item2", Arrays.asList("Tag3", "Tag4"), new BigDecimal("29.99"), 1); List<Item> items = Arrays.asList(item1, item2); Customer customer = new Customer("Male", 30, "customer@example.com", 5); return new Sales(new ObjectId(), new Date(), items, "Store1", customer, true, "Online");}
3

以下代码测试 findAll() 方法:

@Testpublic void testFindAll() { List<Sales> salesList = salesRepository.findAll(); assertThat(salesList).isNotEmpty(); assertThat(salesList.size()).isEqualTo(1); Sales sales = salesList.get(0); assertThat(sales.getStoreLocation()).isEqualTo("Store1"); assertThat(sales.getCustomer().getEmail()).isEqualTo("customer@example.com"); assertThat(sales.getItems()).hasSize(2);}

此测试验证以下内容:

  • 查询正好返回 2 个文档

  • 每个文档都有一个 title字段

  • 每个文档均不包含 _id字段