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

Spring Boot集成测试:如何用Testcontainers控制Docker Compose启停时机?

用Testcontainers实现Docker Compose服务与Spring Boot集成测试的生命周期管理

完全可以通过Testcontainers的Docker Compose模块实现你的需求,它能精准控制容器的启动、就绪检查和停止时机,确保Spring应用依赖的数据库、消息队列等服务在应用启动前就完全就绪,且在测试全部结束后再停止,彻底避免连接失败或提前关闭的问题。

步骤1:添加Testcontainers依赖

在你的构建文件中加入Testcontainers的Docker Compose及JUnit支持依赖(以Maven为例):

<dependency>
    <groupId>org.testcontainers</groupId>
    <artifactId>docker-compose</artifactId>
    <version>1.19.0</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.testcontainers</groupId>
    <artifactId>junit</artifactId>
    <version>1.19.0</version>
    <scope>test</scope>
</dependency>

步骤2:修改集成测试类

调整你的测试代码,加入Testcontainers容器管理和动态配置逻辑:

@RunWith(SpringRunner.class)
@SpringBootTest(classes = MySpringApplication.class, webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT)
public class UspControllerIT {

    // @ClassRule确保容器在测试类初始化前启动,所有测试完成后销毁
    @ClassRule
    public static DockerComposeContainer<?> composeContainer = new DockerComposeContainer<>(new File("docker-compose.yml"))
            // 暴露数据库服务(替换为你docker-compose里的服务名和端口)
            .withExposedService("db", 5432, 
                Wait.forListeningPort().withStartupTimeout(Duration.ofMinutes(2)))
            // 暴露消息队列服务(同理替换为你的服务配置)
            .withExposedService("mq", 5672, 
                Wait.forListeningPort());

    // 动态注入Spring配置,覆盖测试环境的连接参数
    @DynamicPropertySource
    public static void configureTestProperties(DynamicPropertyRegistry registry) {
        // 配置数据库连接
        registry.add("spring.datasource.url", () -> String.format(
            "jdbc:postgresql://%s:%d/your-db-name",
            composeContainer.getServiceHost("db", 5432),
            composeContainer.getServicePort("db", 5432)
        ));
        registry.add("spring.datasource.username", () -> "your-db-user");
        registry.add("spring.datasource.password", () -> "your-db-pwd");

        // 配置消息队列连接
        registry.add("spring.rabbitmq.host", () -> composeContainer.getServiceHost("mq", 5672));
        registry.add("spring.rabbitmq.port", () -> composeContainer.getServicePort("mq", 5672));
    }

    @Test
    public void someIntegrationTest() {
        // 你的测试逻辑
    }
}

关键细节说明

  • @ClassRule的作用:JUnit4中,被@ClassRule修饰的静态容器会在测试类加载阶段启动,所有测试方法执行完毕后才停止,完美匹配「Spring应用启动前依赖服务就绪,测试结束后服务再关闭」的生命周期需求。
  • 服务就绪检查:Wait.forListeningPort()确保服务端口已监听,若需要更严格的健康验证(比如数据库能正常执行查询),可以改用Wait.forCommand()执行容器内的健康检查命令,例如:
    Wait.forCommand("pg_isready -U postgres").withStartupTimeout(Duration.ofMinutes(2))
    
  • 动态配置:@DynamicPropertySource会自动覆盖Spring的配置参数,无需硬编码容器地址和端口(Testcontainers默认会映射随机端口到宿主机器),保证测试环境的灵活性。
  • docker-compose.yml路径:如果你的配置文件不在项目根目录,需调整为正确的相对路径(比如src/test/resources/docker-compose.yml)。

额外注意事项

  • 确保宿主机器已安装Docker,且Testcontainers能正常访问Docker守护进程。
  • 若docker-compose.yml中的服务存在依赖关系,Testcontainers会自动按照依赖顺序启动服务。
  • 可通过withLogConsumer()添加日志输出,方便调试容器启动过程中的问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 21:27:53