Spring Boot采用单例Testcontainers方案时为何启动2个测试容器?
问题原因
你当前的配置之所以会启动两个容器,是因为Testcontainers的复用特性未全局开启,且不同测试上下文加载时静态块可能被重复触发,同时Maven测试插件如果开启了多进程fork也会导致容器重复创建。
解决步骤
1. 重写容器基类,用枚举实现严格单例
枚举是JVM层面保证的单例实现,能确保整个测试生命周期中只有一个容器实例:
import org.springframework.test.context.DynamicPropertyRegistry; import org.springframework.test.context.DynamicPropertySource; import org.testcontainers.containers.PostgreSQLContainer; import org.testcontainers.lifecycle.Startables; public class PostgresTestContainer { // 枚举单例保证全局唯一 enum SingletonPostgresContainer { INSTANCE; private final PostgreSQLContainer<?> container; SingletonPostgresContainer() { container = new PostgreSQLContainer<>("postgres:12") .withDatabaseName("test") .withUsername("postgres") .withPassword("postgres") .withReuse(true); } public PostgreSQLContainer<?> getContainer() { return container; } } static final PostgreSQLContainer<?> postgreSQLContainer = SingletonPostgresContainer.INSTANCE.getContainer(); static { // 异步启动保证容器就绪 Startables.deepStart(postgreSQLContainer).join(); } @DynamicPropertySource static void datasourceConfig(DynamicPropertyRegistry registry) { registry.add("spring.datasource.url", postgreSQLContainer::getJdbcUrl); registry.add("spring.datasource.password", postgreSQLContainer::getPassword); registry.add("spring.datasource.username", postgreSQLContainer::getUsername); } }
2. 开启Testcontainers全局复用配置
在src/test/resources目录下新增testcontainers.properties文件,添加如下配置:
testcontainers.reuse.enable=true
3. 配置Maven测试插件使用单进程
如果测试插件开启了多进程fork,每个进程都会初始化独立的容器,修改pom.xml中Surefire和Failsafe插件配置:
<build> <plugins> <!-- 单元测试插件 --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <version>2.22.2</version> <configuration> <forkCount>1</forkCount> <reuseForks>true</reuseForks> </configuration> </plugin> <!-- 集成测试插件 --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-failsafe-plugin</artifactId> <version>2.22.2</version> <configuration> <forkCount>1</forkCount> <reuseForks>true</reuseForks> </configuration> <executions> <execution> <goals> <goal>integration-test</goal> <goal>verify</goal> </goals> </execution> </executions> </plugin> </plugins> </build>
可选优化
你当前的Repository测试类使用的是JUnit 4的@RunWith(SpringRunner.class),而你用的是JUnit 5,Spring Boot 2.5+的@DataJpaTest已经默认集成了Spring拓展,直接删除该注解即可,避免版本冲突。
内容的提问来源于stack exchange,提问作者wick3d
相关产品推荐
相关产品推荐

