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

Quarkus 2.2测试Mutiny响应式事务代码报错:无法从IO线程启动JTA事务

问题原因分析
  • 你的代码中出现了嵌套Uni结构Uni<Uni<Integer>>,没有展开内层Uni是直接调用assertCompleted()收不到完成事件的核心原因:外层Uni触发完成时,内层的实际操作还未执行。你最后一步的Uni.createFrom().item(prestationRepository.deleteAll())写法错误,如果deleteAll本身已经返回Uni<Integer>,额外套Uni.createFrom().item()会直接把整个Uni作为外层Uni的元素,形成嵌套结构,不需要额外包裹。
  • 默认JTA事务属于阻塞API,直接在IO线程调用就会抛出BlockingOperationNotAllowedException,Quarkus针对响应式场景提供了专属的事务支持,不需要手动切换线程到阻塞执行器。
修复方案

第一步:引入响应式事务依赖(未引入时需要补充)

在pom.xml中添加Quarkus响应式事务扩展:

<dependency>
    <groupId>io.quarkus</groupId>
    <artifactId>quarkus-narayana-r2dbc</artifactId>
</dependency>

如果使用Hibernate Reactive作为持久层,确保已经引入对应的响应式持久化扩展。

第二步:修改测试代码

给测试方法添加@TestReactiveTransaction注解处理测试场景的事务管理,同时调整代码消除Uni嵌套,不需要手动指定runSubscriptionOn,修改后代码如下:

@TestReactiveTransaction
void myTest() {
    final Prestation prestation = Prestation.builder().build();
    // 全程使用transformToUni避免Uni嵌套,最终得到Uni<Integer>结构
    final Uni<Integer> result = Uni.createFrom().voidItem()
            .transformToUni(unused -> prestationCreate.upsert(prestation))
            .transformToUni(aBoolean -> 
                prestationClosedThePreviousDaySelect.select2Multi(LocalDate.of(2021, 04, 29))
                        .collect().asList()
            )
            // 直接返回deleteAll的Uni,不要额外包Uni.createFrom().item()
            .transformToUni(prestations -> prestationRepository.deleteAll());

    // 直接订阅最终的Uni等待结果即可
    result.subscribe().withSubscriber(UniAssertSubscriber.create())
            .awaitItem()
            .assertCompleted();
}

补充说明

如果你的业务方法(如upsert、deleteAll)需要事务支持,直接给对应方法加@ReactiveTransactional注解即可,该注解会自动绑定响应式场景的事务生命周期,不会阻塞IO线程,也不需要手动切换线程池。
如果需要在测试中手动控制事务边界,也可以用QuarkusTransaction的响应式API手动包裹逻辑:

Uni<Integer> result = QuarkusTransaction.requiringNew()
        .call(() -> {
            // 此处为事务内逻辑
            return prestationCreate.upsert(prestation)
                    .chain(() -> prestationClosedThePreviousDaySelect.select2Multi(LocalDate.of(2021, 04, 29)).collect().asList())
                    .chain(prestations -> prestationRepository.deleteAll());
        });

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 10:15:04