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

Spring Boot项目Testcontainers异常启动两个容器测试失败如何解决

问题根因

你使用的Testcontainers JDBC自动启动模式,会在每次解析带tc:前缀的JDBC URL时触发容器创建。Spring Boot的初始化流程中,Flyway自动配置会先加载并解析JDBC URL创建第一个容器,执行迁移脚本;之后Hikari连接池初始化时会再次解析同个JDBC URL,触发第二个容器的创建,第一个容器随之被销毁,最终第二个容器没有执行Flyway脚本导致测试失败。

解决方案

方案1:添加容器可重用配置(改动最小)

在现有JDBC URL后追加&TC_REUSABLE=true参数,同时在本地~/.testcontainers.properties文件中添加配置testcontainers.reuse.enable=true,多次解析同个JDBC URL时会复用已启动的容器,不会重复创建。

修改后的数据源配置如下:

spring.flyway.locations = classpath:database/structure,classpath:database/data
spring.datasource.url=jdbc:tc:postgresql:13.3:///databasename?TC_INITSCRIPT=file:src/test/resources/database/dataset/add_user.sql&TC_REUSABLE=true

方案2:显式声明容器实例(稳定性更高,推荐)

放弃JDBC URL自动启动的方式,在抽象测试类中显式声明静态PostgreSQL容器,配合Spring动态属性注入绑定数据源,全程只会启动一个容器。

  1. 引入Testcontainers JUnit 5集成依赖:
<!-- Maven示例 -->
<dependency>
    <groupId>org.testcontainers</groupId>
    <artifactId>junit-jupiter</artifactId>
    <version>1.15.3</version>
    <scope>test</scope>
</dependency>
  1. 修改抽象测试类代码:
@ExtendWith({RestDocumentationExtension.class, SpringExtension.class})
@TestPropertySource(locations = "classpath:application-test.properties")
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
@Testcontainers
public abstract class AbstractIntegrationTest {
    // 静态容器全局仅初始化一次
    static PostgreSQLContainer<?> postgres = new PostgreSQLContainer<>("postgres:13.3")
            .withInitScript("database/dataset/add_user.sql")
            .withReuse(true);

    // 动态注入数据源配置到Spring上下文
    @DynamicPropertySource
    static void registerPgProperties(DynamicPropertyRegistry registry) {
        registry.add("spring.datasource.url", postgres::getJdbcUrl);
        registry.add("spring.datasource.username", postgres::getUsername);
        registry.add("spring.datasource.password", postgres::getPassword);
    }
//...
}
  1. 删除application-test.properties中原有的带tc:前缀的spring.datasource.url配置。

方案3:对齐Flyway与主数据源配置

在application-test.properties中添加配置,强制Flyway复用主数据源的配置,避免Flyway单独触发容器创建:

spring.flyway.url=${spring.datasource.url}
spring.flyway.user=${spring.datasource.username}
spring.flyway.password=${spring.datasource.password}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.15 15:36:03