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

Spring Boot集成Testcontainers与Flyway启动失败求助

问题:Spring Boot集成Testcontainers启动失败(Flyway连接拒绝)

问题详情

开发Spring Boot应用时集成Testcontainers,其余功能正常,但应用启动失败,报错连接被拒绝,根源是Flyway Bean初始化失败。

核心报错信息

Message: Connection to localhost:32868 refused. Check that the hostname and port are correct and that the postmaster is accepting TCP/IP connections.

完整报错栈

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaConfiguration.class]: Failed to initialize dependency 'flywayInitializer' of LoadTimeWeaverAware bean 'entityManagerFactory': Error creating bean with name 'flywayInitializer' defined in class path resource [org/springframework/boot/autoconfigure/flyway/FlywayAutoConfiguration$FlywayConfiguration.class]: Unable to obtain connection from database: Connection to localhost:32868 refused. Check that the hostname and port are correct and that the postmaster is accepting TCP/IP connections.

测试代码

@Testcontainers
@SpringBootTest
@AutoConfigureMockMvc
public class OwnerRestControllerTest {

    @Container
    @ServiceConnection
    static PostgreSQLContainer<?> postgresContainer =
            new PostgreSQLContainer<>(DockerImageName.parse("postgres:17-alpine"));

    @Autowired
    private MockMvc mockMvc;

    @Autowired
    private OwnerRepository ownerRepository;

    @Test
    @Sql(scripts = "classpath:insert-owners.sql", executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD)
    @Sql(scripts = "classpath:delete-owners.sql", executionPhase = Sql.ExecutionPhase.AFTER_TEST_METHOD)
    public void getAll() throws Exception {
        mockMvc.perform(get("/rest/owners")
                        .param("lastNameContains", "Doe"))
                .andExpect(status()
                        .isOk())
                .andExpect(jsonPath("$.content[*].lastName").value(everyItem(is("Doe"))))
                .andExpect(jsonPath("$.content.length()").value(2));
    }
}

临时解决方案(不推荐)

在测试类中添加休眠等待容器启动:

@Testcontainers
@SpringBootTest
@AutoConfigureMockMvc
public class OwnerRestControllerTest {

    @BeforeAll
    static void beforeAll() throws InterruptedException {
        Thread.sleep(5000);
    }
}

更优解决方案

这不属于Bug,通常是容器就绪检测不充分或版本兼容问题导致的,以下是几种靠谱的解决方式:

1. 增强容器健康检查机制

PostgreSQLContainer默认的健康检查可能只检测端口开放,但Postgres启动后还需要时间完成初始化。可以显式配置更严格的健康检查,延长超时时间:

static PostgreSQLContainer<?> postgresContainer = new PostgreSQLContainer<>(DockerImageName.parse("postgres:17-alpine"))
        .withHealthCheckStrategy(new JdbcDatabaseContainerHealthCheckStrategy()
                .withStartupTimeout(Duration.ofSeconds(30)));

2. 确保版本兼容性

Spring Boot 3.x需要搭配Testcontainers 1.18.0及以上版本,若版本不匹配会导致@ServiceConnection等注解无法正常协同工作,检查pom.xml或build.gradle中的依赖版本。

3. 打印容器日志排查

添加日志消费者,查看Postgres容器的启动日志,确认数据库是否真的完成初始化:

postgresContainer.withLogConsumer(outputFrame -> System.out.println("Postgres 容器日志: " + outputFrame.getUtf8String()));

4. 调整Flyway初始化配置

可以通过Spring Boot配置,让Flyway在尝试连接时增加重试次数:
在测试用的application.properties中添加:

spring.flyway.connect-retries=5
spring.flyway.connect-retry-interval=2

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 12:07:34