SpringBootTest结合WebTestClient时Repository插入数据不生效问题
问题根因
- 测试类上的
@Transactional注解仅绑定测试主线程的事务上下文,而WebFlux默认启动独立的Netty服务器处理请求,所有接口逻辑运行在Netty EventLoop线程,和测试主线程不属于同一个事务上下文。你尝试的persistAndFlush/saveAllAndFlush仅将数据写入当前事务缓冲区,事务未提交时其他线程的JDBC连接无法读取到这部分数据,因此无效。 - 若项目同时引入了Spring Web和WebFlux依赖,会导致Spring初始化两个独立的应用上下文,测试和业务逻辑分别拿到不同的Repository实例,也会出现数据不互通的问题。
解决方案
方案1(推荐,改动最小):调整测试的Web环境为模拟模式
修改@SpringBootTest注解,指定webEnvironment为模拟模式,让WebTestClient的请求直接在测试主线程执行,共享事务上下文:
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.MOCK) @AutoConfigureWebTestClient(timeout = "60000") @Transactional class PaymentControllerIntegrationTest extends Specification { // 其余代码保持不变 }
该方案不需要修改业务逻辑,也能保留测试自动回滚的特性,不需要手动清理测试数据。
方案2:移除测试类的@Transactional注解
如果需要启动真实Netty服务器做端到端测试,直接删除测试类上的@Transactional注解,让测试中插入的数据直接提交到数据库:
- 建议配合H2内存测试库使用,每个测试启动时自动重建表,不会有数据残留问题
- 也可以在每个测试的cleanup阶段手动调用Repository的删除方法清理数据
方案3:排查上下文冲突
如果上述方案无效,检查依赖是否同时引入了spring-boot-starter-web和spring-boot-starter-webflux,在启动类或者测试类上排除WebMVC自动配置,避免双上下文冲突:
@EnableAutoConfiguration(exclude = {WebMvcAutoConfiguration.class})
如果你已经将JPA Repository切换为R2DBC响应式Repository,原有JDBC事务管理器不支持响应式事务,这种场景也建议直接移除测试的@Transactional注解,用内存库处理测试数据即可。
内容的提问来源于stack exchange,提问作者Samuel Lindblom
相关产品推荐
相关产品推荐

