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
相关产品推荐
相关产品推荐

