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

Quarkus 3.7.3中@TestReactiveTransaction未回滚问题求助

问题

在Quarkus 3.7.3中编写单元测试验证PanacheBaseRepository方法时,测试执行后数据库中插入的数据未被回滚。

Repository实现代码

@ApplicationScoped
@WithTransaction
public class FieldRepository implements PanacheRepositoryBase<FieldEntity, UUID> {

    public Uni<FieldEntity> updatePreview(UUID id, JsonObject value) {
        return update("previewValue = ?1, updated = true where id= ?2", value, id)
                .replaceWith(findById(id));
    }
}

测试代码(写法一)

@QuarkusTest
@TestReactiveTransaction
class AttributeRepositoryTest2 {

    @Test
    void shouldUpdateEntity(UniAsserter asserter) {
        FieldEntity entity = new FieldEntity();
        var updatedValue = "updatedValue";
        
        asserter.execute(() -> fieldRepository.persist(entity))
                .assertThat(() -> fieldRepository.updatePreview(entity.id, updatedValue),
                        fieldEntity -> Assertions.assertThat(fieldEntity)
                                .extracting(field -> field.previewValue, field -> field.updated)
                                .contains(updatedValue, true))
                .surroundWith(u -> Panache.withTransaction(() -> u));
    }
}

测试代码(写法二)

@QuarkusTest
@TestReactiveTransaction
class AttributeRepositoryTest2 {

    @Test
    void shouldUpdateEntity(UniAsserter asserter) {
        FieldEntity entity = new FieldEntity();
        var updatedValue = "updatedValue";
        
        asserter.assertThat(() -> fieldRepository.persist(entity).chain(field -> fieldRepository.updatePreview(field.id, updatedValue)),
                        fieldEntity -> Assertions.assertThat(fieldEntity)
                                .extracting(field -> field.previewValue, field -> field.updated)
                                .contains(updatedValue, true))
                .surroundWith(u -> Panache.withTransaction(() -> u));
    }
}

两种写法均出现同一问题:事务未回滚,数据库中新增了记录。


解决方案

问题根源在于事务管理的重复嵌套与冲突:

  1. 测试类事务注解与手动事务调用冲突
    测试类上的@TestReactiveTransaction注解会自动为整个测试方法创建并管理响应式事务,测试结束后自动回滚。但你额外调用了surroundWith(u -> Panache.withTransaction(() -> u)),相当于在已有事务外层再套一层新事务,打乱了原有的测试事务管理逻辑,导致回滚失效。

  2. Repository层的@WithTransaction引发事务边界混乱
    FieldRepository类上的@WithTransaction会让每个Repository方法自动开启新事务,与测试类的@TestReactiveTransaction叠加后,事务边界变得模糊,最终无法触发测试后的回滚操作。

修正步骤:

  • 移除测试代码中的surroundWith(u -> Panache.withTransaction(() -> u))调用,交由@TestReactiveTransaction全权管理测试事务。
  • 删除FieldRepository类上的@WithTransaction注解。生产环境如需事务支持,可在业务方法上添加@WithTransaction,或在Repository方法内部通过Panache.withTransaction()包裹逻辑,灵活控制事务边界。

修正后的测试代码

@QuarkusTest
@TestReactiveTransaction
class AttributeRepositoryTest2 {

    @Test
    void shouldUpdateEntity(UniAsserter asserter) {
        FieldEntity entity = new FieldEntity();
        var updatedValue = "updatedValue";
        
        asserter.execute(() -> fieldRepository.persist(entity))
                .assertThat(() -> fieldRepository.updatePreview(entity.id, updatedValue),
                        fieldEntity -> Assertions.assertThat(fieldEntity)
                                .extracting(field -> field.previewValue, field -> field.updated)
                                .contains(updatedValue, true));
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 11:53:13