From a45b9830cde83c7c88c510f61c416032fc0ce15d Mon Sep 17 00:00:00 2001 From: admin Date: Wed, 29 Jul 2026 22:03:56 +0200 Subject: [PATCH] Add withInitScript support to MongoDBContainer (#3066) When an init script is placed in /docker-entrypoint-initdb.d/, MongoDB shuts down and restarts after executing it. The existing wait strategy only waited for one "waiting for connections" log line, so startup appeared to complete before the restart, causing intermittent failures. withInitScript(MountableFile) copies the script into the container at startup. When used together with withReplicaSet(), the wait strategy is automatically bumped to expect the log message twice, covering the extra restart MongoDB performs after running init scripts. Signed-off-by: klouds27 --- .../mongodb/MongoDBContainer.java | 22 +++++++++++ .../mongodb/MongoDBContainerTest.java | 37 +++++++++++++++++++ modules/mongodb/src/test/resources/init-db.js | 2 + 3 files changed, 61 insertions(+) create mode 100644 modules/mongodb/src/test/resources/init-db.js diff --git a/modules/mongodb/src/main/java/org/testcontainers/mongodb/MongoDBContainer.java b/modules/mongodb/src/main/java/org/testcontainers/mongodb/MongoDBContainer.java index c61be6675ba..a6b482e0769 100644 --- a/modules/mongodb/src/main/java/org/testcontainers/mongodb/MongoDBContainer.java +++ b/modules/mongodb/src/main/java/org/testcontainers/mongodb/MongoDBContainer.java @@ -10,6 +10,8 @@ import org.testcontainers.utility.MountableFile; import java.io.IOException; +import java.util.ArrayList; +import java.util.List; /** * Testcontainers implementation for MongoDB. @@ -45,6 +47,8 @@ public class MongoDBContainer extends GenericContainer { private boolean rsEnabled; + private final List initScripts = new ArrayList<>(); + public MongoDBContainer(@NonNull String dockerImageName) { this(DockerImageName.parse(dockerImageName)); } @@ -61,6 +65,12 @@ protected void containerIsStarting(InspectContainerResponse containerInfo) { if (this.shardingEnabled) { copyFileToContainer(MountableFile.forClasspathResource("/sharding.sh", 0777), STARTER_SCRIPT); } + for (int i = 0; i < initScripts.size(); i++) { + copyFileToContainer(initScripts.get(i), "/docker-entrypoint-initdb.d/init-" + i + ".js"); + } + if (this.rsEnabled && !initScripts.isEmpty()) { + waitingFor(Wait.forLogMessage("(?i).*waiting for connections.*", 2)); + } } @Override @@ -161,6 +171,18 @@ public MongoDBContainer withReplicaSet() { return this; } + /** + * Adds a JavaScript init script to be executed by MongoDB on first startup. + * Scripts are copied to {@code /docker-entrypoint-initdb.d/} and run in the order they were added. + * + * @param initScript the script to copy into the container + * @return this + */ + public MongoDBContainer withInitScript(MountableFile initScript) { + this.initScripts.add(initScript); + return this; + } + /** * Enables sharding on the cluster * diff --git a/modules/mongodb/src/test/java/org/testcontainers/mongodb/MongoDBContainerTest.java b/modules/mongodb/src/test/java/org/testcontainers/mongodb/MongoDBContainerTest.java index 816243d769e..94c4350d0ca 100644 --- a/modules/mongodb/src/test/java/org/testcontainers/mongodb/MongoDBContainerTest.java +++ b/modules/mongodb/src/test/java/org/testcontainers/mongodb/MongoDBContainerTest.java @@ -1,6 +1,10 @@ package org.testcontainers.mongodb; +import com.mongodb.client.MongoClient; +import com.mongodb.client.MongoClients; +import org.bson.Document; import org.junit.jupiter.api.Test; +import org.testcontainers.utility.MountableFile; import static org.assertj.core.api.Assertions.assertThat; @@ -38,4 +42,37 @@ void shouldTestDatabaseName() { assertThat(mongoDBContainer.getReplicaSetUrl(databaseName)).endsWith(databaseName); } } + + @Test + void shouldRunInitScriptWithReplicaSet() { + try ( + MongoDBContainer mongoDBContainer = new MongoDBContainer("mongo:4.0.10") + .withReplicaSet() + .withInitScript(MountableFile.forClasspathResource("init-db.js")) + ) { + mongoDBContainer.start(); + + try (MongoClient client = MongoClients.create(mongoDBContainer.getReplicaSetUrl("testdb"))) { + Document doc = client.getDatabase("testdb").getCollection("items").find().first(); + assertThat(doc).isNotNull(); + assertThat(doc.getString("name")).isEqualTo("testcontainers"); + } + } + } + + @Test + void shouldRunInitScriptWithoutReplicaSet() { + try ( + MongoDBContainer mongoDBContainer = new MongoDBContainer("mongo:4.0.10") + .withInitScript(MountableFile.forClasspathResource("init-db.js")) + ) { + mongoDBContainer.start(); + + try (MongoClient client = MongoClients.create(mongoDBContainer.getConnectionString())) { + Document doc = client.getDatabase("testdb").getCollection("items").find().first(); + assertThat(doc).isNotNull(); + assertThat(doc.getString("name")).isEqualTo("testcontainers"); + } + } + } } diff --git a/modules/mongodb/src/test/resources/init-db.js b/modules/mongodb/src/test/resources/init-db.js new file mode 100644 index 00000000000..ec3efeb6b50 --- /dev/null +++ b/modules/mongodb/src/test/resources/init-db.js @@ -0,0 +1,2 @@ +db = db.getSiblingDB('testdb'); +db.items.insertOne({ name: 'testcontainers' });