如何在测试套件中共享Micronaut上下文?解决连接耗尽问题
Spock+MicronautTest 上下文复用与R2DBC事务问题解决方案
核心问题背景
使用@MicronautTest时,默认每个测试类会创建独立的Micronaut上下文,结合已知的Micronaut Test连接泄漏问题,R2DBC线程池的旧上下文无法被正确清理,会导致数据库连接快速耗尽。尝试通过ContextBuilder实现全局上下文复用后,又出现@Transactional(false)失效,触发R2DBC“同步事务无法用于反应式驱动”的错误。
一、实现测试套件级上下文复用
无需使用ContextBuilder,直接利用Micronaut Test内置的共享上下文机制:
- 配置文件方式:在
src/test/resources/application-test.yml中添加全局配置:
所有标记micronaut: test: shared: enabled: true@MicronautTest的测试类会自动复用同一个上下文,避免重复创建引发的连接泄漏。 - 基类继承方式:创建一个抽象基类并启用共享上下文,业务测试类继承该基类:
@MicronautTest(shared = true) abstract class BaseIntegrationSpec extends Specification { }
二、修复R2DBC事务配置冲突
复用上下文时,需确保事务配置适配反应式驱动:
- 替换同步事务注解:
R2DBC属于反应式驱动,不能使用同步的@Transactional注解。若需禁用事务,直接不添加事务注解即可;若要显式控制,使用@ReactiveTransactional:@ReactiveTransactional(propagation = Propagation.NOT_SUPPORTED) def "execute test without transaction"() { // 测试逻辑 } - 配置默认反应式事务管理器:
在application-test.yml中指定默认事务类型为R2DBC,避免同步事务管理器与反应式驱动冲突:micronaut: data: r2dbc: enabled: true transactions: default: r2dbc
三、额外的连接泄漏防护措施
- 调整R2DBC连接池参数:设置合理的连接超时与最大连接数,避免连接耗尽:
r2dbc: pools: default: max-size: 10 idle-timeout: 30s max-life-time: 5m - 测试后清理资源:在测试类的
cleanup()方法中,手动清理闲置连接(根据使用的连接池实现调整):def cleanup() { def connectionPool = applicationContext.getBean(ConnectionPool) // 触发连接池清理逻辑,如释放闲置连接 }
内容的提问来源于stack exchange,提问作者piotrd
相关产品推荐
相关产品推荐

