Spring Boot Testcontainers启动多个PostgreSQL实例问题咨询
问题根源
你现在的问题是同时混用了两种Testcontainers使用方式:手动创建PostgreSQLContainer实例,又通过jdbc:tc:前缀的URL触发了Testcontainers JDBC驱动自动创建容器,导致两个PostgreSQL实例启动,且版本不一致。此外测试代码里还存在属性key错误、Flyway用户名密码搞反的问题,进一步加剧了异常。
解决方案二选一即可
方案一:手动管理Testcontainers容器(推荐,更灵活)
完全由你控制容器版本与配置,不依赖JDBC驱动自动创建容器。
1. 修正测试代码
@SpringBootTest @AutoConfigureMockMvc @Testcontainers class SpringTestJenkinsApplicationTests { @Container private static final PostgreSQLContainer<?> postgreSQLContainer = new PostgreSQLContainer<>("postgres:15.2-bullseye") .withDatabaseName("postgres") .withUsername("root") .withPassword("root"); @DynamicPropertySource public static void overrideProps(DynamicPropertyRegistry registry) { // 直接使用容器原生JDBC URL,无需添加tc前缀 final String jdbcUrl = postgreSQLContainer.getJdbcUrl(); System.out.println(jdbcUrl); // 修正属性key:去掉末尾多余的= registry.add("spring.datasource.url", () -> jdbcUrl); registry.add("spring.datasource.username", postgreSQLContainer::getUsername); registry.add("spring.datasource.password", postgreSQLContainer::getPassword); // 修正Flyway用户名密码(之前搞反了) registry.add("spring.flyway.url", () -> jdbcUrl); registry.add("spring.flyway.user", postgreSQLContainer::getUsername); registry.add("spring.flyway.password", postgreSQLContainer::getPassword); } @Autowired private MockMvc mockMvc; @Test public void getAllMessages() throws Exception { mockMvc.perform(MockMvcRequestBuilders.get("/v1/api/message") .accept(MediaType.APPLICATION_JSON)) .andExpect(status().isOk()) .andReturn(); } }
2. 修正测试配置文件
server: port: 8080 spring: application: name: chat-api datasource: # 删除Testcontainers驱动配置,改用原生PostgreSQL驱动 jpa: hibernate: # 修正拼写错误:原配置是hibernates ddl-auto: create properties: hibernate: dialect: org.hibernate.dialect.PostgreSQL95Dialect format_sql: true show-sql: false flyway: schemas: public enabled: false default-schema: public
方案二:用Testcontainers JDBC驱动自动管理容器
无需手动创建容器,由JDBC驱动自动创建并管理,只需在URL中指定版本。
1. 修正测试代码
@SpringBootTest @AutoConfigureMockMvc @Testcontainers class SpringTestJenkinsApplicationTests { @DynamicPropertySource public static void overrideProps(DynamicPropertyRegistry registry) { // 直接指定带版本的tc格式URL final String jdbcUrl = "jdbc:tc:postgresql:15.2-bullseye:///postgres?loggerLevel=OFF"; System.out.println(jdbcUrl); registry.add("spring.datasource.url", () -> jdbcUrl); registry.add("spring.datasource.username", () -> "root"); registry.add("spring.datasource.password", () -> "root"); registry.add("spring.flyway.url", () -> jdbcUrl); registry.add("spring.flyway.user", () -> "root"); registry.add("spring.flyway.password", () -> "root"); } @Autowired private MockMvc mockMvc; @Test public void getAllMessages() throws Exception { mockMvc.perform(MockMvcRequestBuilders.get("/v1/api/message") .accept(MediaType.APPLICATION_JSON)) .andExpect(status().isOk()) .andReturn(); } }
2. 保留配置文件的驱动设置
server: port: 8080 spring: application: name: chat-api datasource: driver-class-name: org.testcontainers.jdbc.ContainerDatabaseDriver jpa: hibernate: # 修正拼写错误 ddl-auto: create properties: hibernate: dialect: org.hibernate.dialect.PostgreSQL95Dialect format_sql: true show-sql: false flyway: schemas: public enabled: false default-schema: public
问题原因复盘
- 手动创建
postgres:15.2-bullseye容器的同时,又使用jdbc:tc:前缀URL,触发JDBC驱动自动创建默认版本(9.6.12)的容器,导致双实例启动。 - 动态属性key末尾多余的
=,导致部分配置未生效,加剧版本不一致问题。 - Flyway的用户名与密码配置搞反,可能引发连接失败。
内容的提问来源于stack exchange,提问作者Cofi
相关产品推荐
相关产品推荐

