Spring Boot 3.1集成Testcontainers无法连接PostgreSQL求助
问题:Spring Boot Testcontainers 连接PostgreSQL失败
我编写了一个简单的测试用例用于验证数据库连接,但无法成功连接到数据库。
测试用例代码
@End2EndTest @SpringBootTest(classes = [StartPostgresContainerExtensionTestsConfiguration::class]) @Testcontainers class SpringBootPostgresTestcontainerTest( @Autowired private val abrechnungDbDataSource: DataSource?, ) { companion object { @Container @JvmStatic val postgresContainer = PostgreSQLContainer("postgres:13.8-bullseye").also { it.start() } @DynamicPropertySource @JvmStatic fun datasourceProperties(registry: DynamicPropertyRegistry) { registry.add("fonl.databases.abrechnung-db.name", postgresContainer::getDatabaseName) registry.add("fonl.databases.abrechnung-db.username", postgresContainer::getUsername) registry.add("fonl.databases.abrechnung-db.password", postgresContainer::getPassword) registry.add("fonl.databases.abrechnung-db.url", postgresContainer::getJdbcUrl) } } @Test fun `connection to database can be established`() { assertThat(abrechnungDbDataSource).isNotNull checkConnectivity(abrechnungDbDataSource!!) } private fun checkConnectivity(dataSource: DataSource) { dataSource.connection.isValid(3) val jdbcTemplate = JdbcTemplate(dataSource) val result = jdbcTemplate.queryForObject("SELECT 1", Int::class.java) check(result == 1) } } @Configuration @EnableConfigurationProperties class SpringBootPostgresTestcontainerTestConfiguration { private val log = LoggerFactory.getLogger(javaClass) @Bean @ConfigurationProperties("fonl.databases.abrechnung-db") fun abrechnungDbDataSourceProperties() = DataSourceProperties() @Bean fun abrechnungDbDataSource(abrechnungDbDataSourceProperties: DataSourceProperties): DataSource = abrechnungDbDataSourceProperties.also { logDataSourceProperties(it) }.initializeDataSourceBuilder().build() private fun logDataSourceProperties(dataSourceProperties: DataSourceProperties) { if (log.isDebugEnabled) { log.debug( "DriverClassname=${dataSourceProperties.driverClassName}; " + "DataSourceName=${dataSourceProperties.name}; " + "UserName=${dataSourceProperties.username}; " + "Password=${dataSourceProperties.password}; " + "url=${dataSourceProperties.url}" ) } } }
日志信息
09:36:15.892 [Test worker] INFO tc.postgres:13.8-bullseye - Creating container for image: postgres:13.8-bullseye 09:36:15.903 [Test worker] INFO tc.postgres:13.8-bullseye - Container postgres:13.8-bullseye is starting: 354a1f11fb796abd72af46d855d65849aac7d1e9cb41aa560941ec62b44ff82d 09:36:16.859 [Test worker] INFO tc.postgres:13.8-bullseye - Container postgres:13.8-bullseye started in PT0.967635S 09:36:16.860 [Test worker] INFO tc.postgres:13.8-bullseye - Container is started (JDBC URL: jdbc:postgresql://localhost:32771/test?loggerLevel=OFF) 09:36:16.867 [Test worker] INFO d.a.f.m.t.p.SpringBootPostgresTestcontainerTest - Starting SpringBootPostgresTestcontainerTest using Java 17.0.6 with PID 7635 (started by alexander.rolfes in /Users/alexander.rolfes/sources/allianz/fonl-microlibraries/testing/test-support/test-support-postgres) 09:36:16.867 [Test worker] DEBUG d.a.f.m.t.p.SpringBootPostgresTestcontainerTest - Running with Spring Boot v3.1.6, Spring v6.0.14 09:36:16.867 [Test worker] INFO d.a.f.m.t.p.SpringBootPostgresTestcontainerTest - The following 2 profiles are active: "test", "end2end-test" 09:36:17.477 [Test worker] DEBUG d.a.f.m.t.p.StartPostgresContainerExtensionTestsConfiguration$$SpringCGLIB$$0 - DriverClassname=org.postgresql.Driver; DataSourceName=test; UserName=test; Password=test; url=jdbc:postgresql://localhost:32771/test?loggerLevel=OFF 09:36:17.507 [Test worker] INFO d.a.f.m.t.p.SpringBootPostgresTestcontainerTest - Started SpringBootPostgresTestcontainerTest in 4.295 seconds (process running for 5.297) 09:36:17.579 [Test worker] INFO com.zaxxer.hikari.HikariDataSource - HikariPool-1 - Starting... 09:36:18.628 [Test worker] ERROR com.zaxxer.hikari.pool.HikariPool - HikariPool-1 - Exception during pool initialization. org.postgresql.util.PSQLException: Connection to localhost:32771 refused. Check that the hostname and port are correct and that the postmaster is accepting TCP/IP connections.
问题原因及解决方法
手动启动容器导致时序异常
你在初始化postgresContainer时手动调用了.also { it.start() },但Testcontainers框架会自动管理容器的生命周期(启动、健康检查、停止)。手动提前启动会导致Spring上下文初始化时,PostgreSQL服务可能还未完全就绪,或者端口映射未正确同步。解决:删除手动启动代码,让框架自动处理:
@Container @JvmStatic val postgresContainer = PostgreSQLContainer("postgres:13.8-bullseye")容器健康检查未生效
手动启动容器会跳过Testcontainers默认的健康检查逻辑,即使日志显示容器已启动,PostgreSQL内部服务可能还在初始化,此时尝试连接必然失败。依赖框架的自动启动逻辑,会等待容器的健康检查通过后再初始化Spring上下文。Docker网络映射问题(可选排查)
如果是Docker Desktop环境,偶尔会出现localhost映射异常,此时可以尝试使用postgresContainer.host替代localhost,不过getJdbcUrl()已经自动包含了正确的主机地址,所以只要删除手动启动代码,这个问题也会随之解决。
内容的提问来源于stack exchange,提问作者Alex
相关产品推荐
相关产品推荐

