Spring Boot集成Testcontainers测试: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

