【问题标题】:How do I configure embedded MongoDB with authentication for use in spring boot integration tests?如何使用身份验证配置嵌入式 MongoDB 以在 Spring Boot 集成测试中使用?
【发布时间】:2018-07-04 02:54:26
【问题描述】:

我有一个使用 MongoDB 进行持久性的 Spring Boot 应用程序。我正在整理集成测试,并且我正在为嵌入式数据库使用 flapdoodle embedded mongo 库。

这与弹簧靴自动配置相结合,一切都非常适合集成测试。但是,一旦我为 MongoDB 添加了身份验证凭据,一切就崩溃了。

我的理解是spring auto-configure找到了凭证并尝试通过身份验证连接到数据库,但失败了,因为它是一个尚未使用凭证初始化的嵌入式数据库。

我尝试使用mongeez 来初始化春季启动前的凭据,但这个库在凭据感应方面存在同样的问题。

所以我真正的问题:

有没有办法通过身份验证初始化嵌入式数据库?我一直在挖掘源代码,但没有找到任何东西。

【问题讨论】:

  • 您可以为 prod 和 integ-tests 添加当前配置吗?
  • 我遇到了同样的问题。很想知道这是否/何时得到回答。我收到 com.mongodb.MongoSecurityException: Exception authenticationing MongoCredential
  • @user26270,不幸的是我从来没有找到办法做到这一点。相反,我必须做的是从配置中完全删除凭据,并在生产部署期间在运行时添加它们。因此集成测试将无法测试身份验证。

标签: java mongodb spring-boot spring-data spring-data-mongodb


【解决方案1】:

我遇到了同样的问题。这就是它对我的工作方式(使用 Kotlin):

@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, properties = ["spring.data.mongodb.port="])
class IntegrationTests {

@Autowired
private val webClient: WebTestClient? = null

@Autowired
private val mongoConfig: IMongodConfig? = null
var collection: MongoCollection<Document>? = null

fun createDBAndCollection(collectionName: String){
    val mongo = MongoClient("127.0.0.1", mongoConfig!!.net().port)
    val db = mongo.getDatabase("local")
    db.createCollection(collectionName)
    collection = db.getCollection(collectionName)
}

@Test
fun `Find all tracks on JSON REST endpoint`() {
    createDBAndCollection("track")
    collection?.insertOne(Document("key", "val"))

    webClient!!.get().uri("/reactive/tracks")
            .accept(APPLICATION_JSON)
            .exchange()
            .expectStatus().is2xxSuccessful
            .expectBodyList<Track>()
            .hasSize(1);
}
}
  • 无需更改 application.properties。使用 SprintBootTest 注释清空端口设置就足够了(其他方法对我不起作用,例如 @TestPropertySource)
  • mongoConfig 被注入并用于检索由fladdoodle 生成的随机端口
  • 数据库名称必须与 application.properties 中的名称匹配(但我确信有一种方法可以在运行时动态读取它)。

我的 gradle 测试依赖项是:

testImplementation('de.flapdoodle.embed:de.flapdoodle.embed.mongo')
testImplementation('io.projectreactor:reactor-test')
testImplementation('org.springframework.boot:spring-boot-starter-test')
testImplementation("org.junit.jupiter:junit-jupiter-api")
testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine")

【讨论】:

    【解决方案2】:

    实际上,您可以通过查看admin.system.users 集合来创建经过身份验证的用户。只需创建一个测试用户并将其与 mongo 客户端一起放在那里。只要您在那里有一个用户,您就可以转储该文档并使用该 json 在您的嵌入式 mongo 测试套件中创建一个新的经过身份验证的用户。应该是这样的:

    private static void createAuthorizationUser() {
        MongoClient mongoClient = new MongoClient(HOST);
        MongoDatabase admin = mongoClient.getDatabase("admin");
        MongoCollection<Document> usersCollection = admin.getCollection("system.users");
        usersCollection.insertOne(Document.parse(""
                + "{\n" + 
                "    \"_id\": \"admin.test-user\",\n" + 
                //"    \"userId\": Binary(\"rT2Ig**********jGXZEQ==\", 4),\n" + 
                "    \"user\": \"test-user\",\n" + 
                "    \"db\": \"admin\",\n" + 
                "    \"credentials\": {\n" + 
                "        \"SCRAM-SHA-1\": {\n" + 
                "            \"iterationCount\": 10000,\n" + 
                "            \"salt\": \"gmm******GnNcAw==\",\n" + 
                "            \"storedKey\": \"qE***********8/LAvG7s=\",\n" + 
                "            \"serverKey\": \"Re*********eQh6w=\"\n" + 
                "        }\n" + 
                "    },\n" + 
                "    \"roles\": [\n" + 
                "        {\n" + 
                "            \"role\": \"readWrite\",\n" + 
                "            \"db\": \"test\"\n" + 
                "        }\n" + 
                "    ]\n" + 
                "}"
                + ""));
    }
    

    我创建了一个名为 test-user 的用户,该用户对测试数据库具有读写权限。出于某种原因,嵌入式 Mongo 不喜欢 Binary 功能,但只是评论它不会损害身份验证功能。

    创建客户端时,您可以简单地通过

    MongoClient mongoClient = new MongoClient(
        new MongoClientURI( 
            String.format("mongodb://%s:%s@%s:%d/%s", "test-user", "****", "localhost", 27017, "admin" ) 
        )
    );
    

    它应该可以解决问题。

    【讨论】:

      猜你喜欢
      • 2016-08-26
      • 2016-12-11
      • 2017-11-12
      • 1970-01-01
      • 2018-03-28
      • 1970-01-01
      • 2017-02-25
      • 2022-01-19
      • 1970-01-01
      相关资源
      最近更新 更多