0

I am able to start the mongo image, insert and read data just fine using the snippet below. Similar to the redis example on testcontainers.org.

private static final int MONGO_PORT = 27017;

@ClassRule
public static MongoDBContainer mongo = new MongoDBContainer("mongo:3.2.4")
        .withExposedPorts(MONGO_PORT);

By default mongo doesn't have credentials but I'm looking for a way to set the credentials so that my app's MongoClient can get user/password from system properties and connect properly. I've tried adding the root user/password with the below but that didn't set the credentials properly.

@ClassRule
public static MongoDBContainer mongo = new MongoDBContainer("mongo:3.2.4")
        .withExposedPorts(MONGO_PORT)
        .withEnv("MONGO_INITDB_ROOT_USERNAME", "admin")
        .withEnv("MONGO_INITDB_ROOT_PASSWORD", "admin");

My question is: How can I start the test container with a username and password to allow my app to connect to it during my integration test using wiremock.

Vitaly Chura
  • 704
  • 8
  • 13
aemorales1
  • 312
  • 3
  • 13

2 Answers2

3

Checking the docs you can have a GenericContainer rather than specifically a MongoDbContainer (not certain this makes much difference given it looks largely like I've got the same as what you've already tried)...

I've then run:

private static final int MONGO_PORT = 27017;

    /**
     * https://hub.docker.com/_/mongo shows:
     *
     * $ docker run -d --network some-network --name some-mongo \
     *     -e MONGO_INITDB_ROOT_USERNAME=mongoadmin \
     *     -e MONGO_INITDB_ROOT_PASSWORD=secret \
     *     mongo
     */
    public static GenericContainer mongo = new GenericContainer(DockerImageName.parse("mongo:4.4.1"));

    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("MONGO_INITDB_ROOT_USERNAME=mongoadministrator");
        list.add("MONGO_INITDB_ROOT_PASSWORD=secret");
        list.add("MONGO_INITDB_DATABASE=db");
        mongo.setEnv(list);
        mongo.withExposedPorts(MONGO_PORT);
        mongo.start();
    }

the logs from the container show: docker logs [container_id]:

...
Successfully added user: {
    "user" : "mongoadministrator",  <<<<<
    "roles" : [
        {
            "role" : "root",
            "db" : "admin"
        }
    ]
}
...

I can login successfully inside the container with my new administrative user:

> docker exec -it 3ae15f01074c bash
Error: No such container: 3ae15f01074c

> docker ps -a
CONTAINER ID        IMAGE                       COMMAND                  CREATED             STATUS              PORTS                      NAMES
755e214f23d6        mongo:4.4.1                 "docker-entrypoint.s…"   2 seconds ago       Up 2 seconds        0.0.0.0:32803->27017/tcp   elegant_keldysh
cdb4f55930f4        testcontainers/ryuk:0.3.0   "/app"                   3 seconds ago       Up 3 seconds        0.0.0.0:32802->8080/tcp    testcontainers-ryuk-ef84751e-bfd4-41eb-b381-1c1206186eda

> docker exec -it 755e214f23d6 bash
root@755e214f23d6:/# mongo admin -u mongoadministrator
MongoDB shell version v4.4.1
Enter password:                      <<<<<<<<<<<<<<<< BAD PASSWORD ENTERED HERE
connecting to: mongodb://127.0.0.1:27017/admin?compressors=disabled&gssapiServiceName=mongodb
Error: Authentication failed. :
connect@src/mongo/shell/mongo.js:374:17
@(connect):2:6
exception: connect failed
exiting with code 1

root@755e214f23d6:/# mongo admin -u mongoadministrator
MongoDB shell version v4.4.1
Enter password:                   <<<<<<<< GOOD PASSWORD secret ENTERED HERE
connecting to: mongodb://127.0.0.1:27017/admin?compressors=disabled&gssapiServiceName=mongodb
Implicit session: session { "id" : UUID("63279398-d9c6-491d-9bd9-6b619dc4a99d") }
MongoDB server version: 4.4.1
Welcome to the MongoDB shell.
For interactive help, type "help".
For more comprehensive documentation, see
    https://docs.mongodb.com/
Questions? Try the MongoDB Developer Community Forums
    https://community.mongodb.com
---
The server generated these startup warnings when booting: 
        2020-10-24T22:06:24.914+00:00: Using the XFS filesystem is strongly recommended with the WiredTiger storage engine. See http://dochub.mongodb.org/core/prodnotes-filesystem
---
---
        Enable MongoDBs free cloud-based monitoring service, which will then receive and display
        metrics about your deployment (disk utilization, CPU, operation statistics, etc).

        The monitoring data will be available on a MongoDB website with a unique URL accessible to you
        and anyone you share the URL with. MongoDB may use this information to make product
        improvements and to suggest MongoDB products and deployment options to you.

        To enable free monitoring, run the following command: db.enableFreeMonitoring()
        To permanently disable this reminder, run the following command: db.disableFreeMonitoring()
---
> 
Rob Evans
  • 2,822
  • 1
  • 9
  • 15
  • I just thought to try your version. It did not work for me - no specific user appears to be registered in the logs. I was able to connect but not login as presumably the default user/pass combination is in place (which I don't know). I see you'd have to use a different library for the mongoDb container `"org.testcontainers:mongodb:1.15.0-rc2"` rather than the standard testcontainers lib `'org.testcontainers:testcontainers:1.15.0-rc2'` (which is what I used for this solution). – Rob Evans Oct 26 '20 at 09:06
  • Did it work? I was hoping to get the bounty on this one? – Rob Evans Oct 28 '20 at 16:07
  • I have the answer to this question but it seems the +100 bounty disappeared??? – Rob Evans Oct 28 '20 at 20:17
  • I realise this is late but to answer your question - you appeared to confusing API/HTTP mocking which wiremock offers, with using a (real) mongo db server (which is not mocked). Hence this should have been the correct answer to your question and won the bounty :) hope you got it sorted either way – Rob Evans Nov 04 '20 at 14:05
  • I've not been able to try it. If this works I'll reopen the bounty and get you the points. I've no intention to back out on the promised bounty. I'll make it a priority to give this a go by the end of today. – aemorales1 Nov 04 '20 at 14:42
  • pls do. I'm trying to increase my score to above 1000 for the quarter to put me in the top 0.5% or whatever it is on SO – Rob Evans Nov 04 '20 at 14:48
  • This gets me past the roadblock. I found that the problem was coming from the version. The user/password were set when I updated to version 4.4.1 like you have in your example. In the end, I used a @TestConfiguration to avoid changing my production code and was okay with leaving the authentication out there. Since my main question was about setting the user name/password and your solution did get me that let's figure out how to give you the bounty :) – aemorales1 Nov 05 '20 at 00:26
  • I'm not seeing it here but I read that I missed the bounty time + grace period but that you'd get the bounty so long as you have at least +2 and the answer is marked complete. I'll stay on top of this, if it doesn't work I don't mind just posting the bounty again and getting you 200 instead of 100 :) – aemorales1 Nov 05 '20 at 00:31
0

In short, you can find working example of test with MongoDB container here.

To provide, more details: you can configure authentication to MongoDB test container by using GenericContainer and setting environment with following properties MONGO_INITDB_ROOT_USERNAME, MONGO_INITDB_ROOT_PASSWORD:

@ClassRule
public static final GenericContainer<?> MONGODB = new GenericContainer<>(DockerImageName.parse(MONGO_IMAGE))
        .withEnv("MONGO_INITDB_ROOT_USERNAME", USERNAME)
        .withEnv("MONGO_INITDB_ROOT_PASSWORD", PASSWORD)
        .withEnv("MONGO_INITDB_DATABASE", TEST_DATABASE)
        .withExposedPorts(MONGO_PORT);

Then you should use MongoClient with corresponding MongoCredential. For example, below is the test, that writes and reads document to/from MongoDB container.

@Test
public void shouldWriteAndReadMongoDocument() {
    ServerAddress serverAddress = new ServerAddress(MONGODB.getHost(), MONGODB.getMappedPort(MONGO_PORT));
    MongoCredential credential = MongoCredential.createCredential(USERNAME, AUTH_SOURCE_DB, PASSWORD.toCharArray());
    MongoClientOptions options = MongoClientOptions.builder().build();

    MongoClient mongoClient = new MongoClient(serverAddress, credential, options);
    MongoDatabase database = mongoClient.getDatabase(TEST_DATABASE);
    MongoCollection<Document> collection = database.getCollection(TEST_COLLECTION);

    Document expected = new Document("name", "foo").append("foo", 1).append("bar", "string");
    collection.insertOne(expected);

    Document actual = collection.find(new Document("name", "foo")).first();
    assertThat(actual).isEqualTo(expected);
}

Notes:

  • To find more details on environment variables, you check documentation here (specifically, Environment Variables section)

  • To find more details on authenticated connection to MongoDB, you check documentation here

Oleksii Zghurskyi
  • 3,967
  • 1
  • 16
  • 17
  • 1
    seems like it requires more intervention. ```org.testcontainers.containers.MongoDBContainer$ReplicaSetInitializationException: An error occurred: MongoDB shell version v4.0.10 connecting to: mongodb://127.0.0.1:27017/?gssapiServiceName=mongodb 2021-06-14T13:31:37.571+0000 E QUERY [js] Error: network error while attempting to run command 'isMaster' on host '127.0.0.1:27017' : connect@src/mongo/shell/mongo.js:344:17 @(connect):2:6``` – Capacytron Jun 14 '21 at 14:28