You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot集成Testcontainers测试:uri配置导致测试失败

解决Testcontainers MongoDB与spring.data.mongodb.uri冲突的问题

问题核心在于:Spring Boot中spring.data.mongodb.uri的配置优先级高于拆分的host/port配置,而@ServiceConnection默认只会覆盖host、port等拆分属性,无法替换已存在的uri配置,导致测试代码连接到了配置文件指定的外部MongoDB服务,而非Testcontainers启动的容器,因此查询不到导入的测试数据。

以下是几种可行的解决方案:

方案一:用@DynamicPropertySource手动注入容器URI

通过@DynamicPropertySource直接向Spring环境注入Testcontainers容器的连接URI,其优先级高于application.properties中的配置,能强制覆盖原有uri设置。

修改TestContainersConfiguration类:

@ActiveProfiles({ "test", "integration" })
@TestConfiguration(proxyBeanMethods = false)
public class TestContainersConfiguration {

    private static MongoDBContainer mongoDBContainer;

    static {
        mongoDBContainer = new MongoDBContainer(DockerImageName.parse("mongo:4.4"));
        mongoDBContainer.start();
        try {
            mongoDBContainer.copyFileToContainer(MountableFile.forClasspathResource("testResources.json"),
                    "/publications.json");
            mongoDBContainer.execInContainer("mongoimport",
                    "--db", "documents",
                    "--mode", "upsert",
                    "--collection", "dspacePublication", "--file",
                    "/publications.json", "--jsonArray", "--quiet");
        } catch (IOException | InterruptedException e) {
            throw new RuntimeException("初始化测试MongoDB数据失败", e);
        }
    }

    @Bean
    public MongoDBContainer mongoDbContainer() {
        return mongoDBContainer;
    }

    @DynamicPropertySource
    static void setMongoDbProperties(DynamicPropertyRegistry registry) {
        // 直接注入容器的完整URI,包含数据库名
        registry.add("spring.data.mongodb.uri", () -> mongoDBContainer.getReplicaSetUrl() + "/documents");
    }
}

方案二:在测试配置文件中覆盖URI

在src/test/resources/application-test.properties中添加占位符配置:

spring.data.mongodb.uri=${TEST_MONGODB_URI}

然后在TestContainersConfiguration中动态设置该环境变量:

@ActiveProfiles({ "test", "integration" })
@TestConfiguration(proxyBeanMethods = false)
public class TestContainersConfiguration {

    @Bean
    public MongoDBContainer mongoDbContainer() throws IOException, InterruptedException {
        var mongoDBContainer = new MongoDBContainer(DockerImageName.parse("mongo:4.4"));
        mongoDBContainer.start();
        mongoDBContainer.copyFileToContainer(MountableFile.forClasspathResource("testResources.json"),
                "/publications.json");
        mongoDBContainer.execInContainer("mongoimport",
                "--db", "documents",
                "--mode", "upsert",
                "--collection", "dspacePublication", "--file",
                "/publications.json", "--jsonArray", "--quiet");
        
        // 设置环境变量覆盖测试配置中的占位符
        System.setProperty("TEST_MONGODB_URI", mongoDBContainer.getReplicaSetUrl() + "/documents");
        return mongoDBContainer;
    }
}

方案三:强制@ServiceConnection覆盖配置(Spring Boot 3.1+)

如果使用Spring Boot 3.1及以上版本,可通过配置强制@ServiceConnection覆盖已有URI设置。在src/test/resources/application-test.properties中添加:

spring.test.service-connection.override=always

此配置会让@ServiceConnection强制替换spring.data.mongodb.uri,无需修改Java代码即可生效。

验证效果:运行SearchControllerIT测试,此时mongoTemplate会正确连接到Testcontainers启动的MongoDB容器,能查询到导入的测试数据。

内容的提问来源于stack exchange,提问作者user25032322

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 02:23:11