使用凭据启动 MongoDb 测试容器

Start MongoDb Test Container with credentials

我可以使用下面的代码片段启动 mongo 图像、插入和读取数据。类似于 testcontainers.org.

上的 redis 示例
private static final int MONGO_PORT = 27017;

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

默认情况下 mongo 没有凭据,但我正在寻找一种方法来设置凭据,以便我的应用程序的 MongoClient 可以从系统属性中获取 user/password 并正确连接。我试过用下面的方法添加根 user/password 但没有正确设置凭据。

@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");

我的问题是:如何使用用户名和密码启动测试容器,以允许我的应用在使用 wiremock 进行集成测试期间连接到它。

检查文档你可以有一个 GenericContainer 而不是具体的 MongoDbContainer (不确定这有多大区别,因为它看起来很像我已经得到的和你已经得到的一样尝试过)...

然后我运行:

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();
    }

容器中的日志显示: docker logs [container_id]:

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

我可以使用我的新管理用户在容器内成功登录:

> 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()
---
> 

简而言之,您可以找到使用 MongoDB 容器 here 进行测试的工作示例。

提供更多详细信息:您可以通过使用 GenericContainer 并使用以下属性设置环境来为 MongoDB 测试容器配置身份验证 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);

那么你应该使用MongoClient和相应的MongoCredential。例如,下面是写入和读取文档 to/from MongoDB 容器的测试。

@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);
}

备注:

  • 要查找有关环境变量的更多详细信息,请查看文档 here(具体来说,环境变量 部分)

  • 要查找有关 MongoDB 的经过身份验证的连接的更多详细信息,请查看文档 here