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

Spring Boot批量执行测试时抛出PSQLException问题排查

问题诊断与解决方案

核心原因分析

你遇到的32这个限制,来源于Spring Boot Test默认的测试上下文缓存最大容量(32)。当批量运行测试时,Spring会为每个“不同”的测试场景创建独立的ApplicationContext,当缓存的上下文数量达到32后,最早创建的上下文会被自动销毁,连带销毁该上下文内的Hikari连接池。后续测试如果意外引用了已被销毁的连接池(比如HikariPool-1),就会抛出「This connection has been closed」异常。

而单独运行测试时,只会创建少量上下文,不会触发缓存驱逐逻辑,因此不会出现问题。

具体解决方案

1. 扩大Spring测试上下文缓存容量

通过系统属性调整缓存的最大大小,避免早期上下文被销毁:

  • 命令行方式:运行测试时添加参数
    mvn test -Dspring.test.context.cache.maxSize=100
    
  • pom.xml配置:在surefire插件中固定配置
    <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-surefire-plugin</artifactId>
        <configuration>
            <systemPropertyVariables>
                <spring.test.context.cache.maxSize>100</spring.test.context.cache.maxSize>
            </systemPropertyVariables>
        </configuration>
    </plugin>
    

2. 确保所有测试复用同一个Spring上下文

检查测试类是否存在导致上下文无法复用的差异化配置:

  • 所有测试类应继承同一个抽象类,且子类不要添加额外的@TestConfiguration、@Profile或@PropertySource注解
  • 确保所有测试使用相同的属性配置,避免因属性差异触发新上下文的创建
  • 可以在抽象类上添加@ContextConfiguration统一指定配置类,强制所有子类复用同一上下文

3. 优化Testcontainers与连接池的绑定逻辑

确保PostgreSQLContainer单例与Spring DataSource的生命周期完全绑定:

  • 使用@DynamicPropertySource动态注入容器的JDBC属性,避免硬编码,确保所有上下文使用同一个容器实例:
    public abstract class AbstractDbTest {
        private static final PostgreSQLContainer<?> POSTGRES_CONTAINER = new PostgreSQLContainer<>("postgres:15-alpine")
                .withReuse(true);
    
        static {
            POSTGRES_CONTAINER.start();
        }
    
        @DynamicPropertySource
        static void registerDbProperties(DynamicPropertyRegistry registry) {
            registry.add("spring.datasource.url", POSTGRES_CONTAINER::getJdbcUrl);
            registry.add("spring.datasource.username", POSTGRES_CONTAINER::getUsername);
            registry.add("spring.datasource.password", POSTGRES_CONTAINER::getPassword);
        }
    }
    
  • 避免在测试类中手动创建DataSource实例,完全依赖Spring自动配置的DataSource,确保连接池全局复用

4. 排查连接泄漏问题

即使测试不直接操作数据库,也可能存在连接泄漏导致连接池被异常关闭:

  • 开启Hikari的调试日志,检查连接的获取与释放情况:
    logging.level.com.zaxxer.hikari=DEBUG
    
  • 确认抽象类中的初始化逻辑是否正确释放了数据库连接,比如是否有未关闭的JdbcTemplate或EntityManager实例

内容的提问来源于stack exchange,提问作者Abdulrahman Humayed

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 01:45:35