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

Quarkus Reactive Panache测试报错:No current Vertx context found

Quarkus+Hibernate Reactive Panache测试:解决"No current Vertx context found"问题

问题背景

我在开发Quarkus项目时,用Hibernate Reactive with Panache实现非阻塞数据库操作,服务方法通过Panache.withTransaction()在事务内创建用户。编写测试用例时,一直触发错误:No current Vertx context found。

已尝试操作

  • 模拟Panache.withTransaction()返回Uni<Auth>
  • 模拟User.persist()
  • 尝试多种模拟方式,均未解决问题

问题认知

  • 错误与Quarkus响应式模型绑定,测试必须在Vert.x上下文内运行
  • 测试环境未正确处理Panache.withTransaction()的异步行为

核心问题

  1. 如何设置测试使其在正确的Vert.x上下文运行以避免错误?
  2. Quarkus中模拟Panache响应式操作是否有特定方式?
  3. 是否有替代方案测试Panache.withTransaction()以规避该问题?

解决方案

1. 让测试在Vert.x上下文内运行

Quarkus响应式测试必须在Vert.x事件循环上下文执行,有两种实现方式:

  • 使用Quarkus原生测试注解:给测试类或方法添加@QuarkusTest,该注解会自动初始化Vert.x上下文,所有测试逻辑都会在事件循环中运行。如果是轻量单元测试,不想启动完整Quarkus应用,可以引入quarkus-junit5-vertx依赖后使用@VertxTest,或者用@ReactiveTransactionalTest专门测试事务逻辑。
  • 手动绑定Vert.x上下文:如果必须使用普通JUnit测试,可手动创建Vertx实例,并将测试逻辑包裹在vertx.runOnContext()中,示例代码:
@Test
void testCreateUser() throws InterruptedException {
    Vertx vertx = Vertx.vertx();
    CountDownLatch latch = new CountDownLatch(1);

    vertx.runOnContext(v -> {
        userService.createUser(new User("test"))
            .subscribe().with(auth -> {
                assertNotNull(auth);
                latch.countDown();
            });
    });

    latch.await(2, TimeUnit.SECONDS);
}

2. Quarkus中模拟Panache响应式操作的正确姿势

Panache Reactive的静态方法(如withTransaction、persist)无法用Mockito直接模拟,因为Panache依赖字节码增强,Mockito拦截不了静态方法调用。推荐两种方式:

  • 封装Panache操作到独立服务层:不要在业务逻辑中直接调用Panache静态方法,而是封装成TransactionService,示例:
@ApplicationScoped
public class TransactionService {
    public <T> Uni<T> executeInTransaction(Function<EntityManager, Uni<T>> action) {
        return Panache.withTransaction(action);
    }
}

业务服务注入TransactionService后,测试时即可用Mockito模拟该服务的方法,避免直接操作Panache静态方法。

  • 使用Quarkus原生Mock支持:如果使用PanacheRepositoryReactive,可以定义一个Mock实现,并用@Mock注解注入测试类,替换真实的Repository实例,示例:
@Mock
@ApplicationScoped
public class MockUserRepository implements PanacheRepositoryReactive<User> {
    @Override
    public Uni<User> persist(User entity) {
        return Uni.createFrom().item(entity);
    }
}

3. 测试Panache.withTransaction()的替代方案

如果不想模拟,希望真实验证事务逻辑,可采用以下方案:

  • 内存数据库集成测试:用@QuarkusTest配合H2内存数据库(或PostgreSQL测试容器),Quarkus会自动配置测试环境的数据库和Vert.x上下文,可真实执行事务操作,无需模拟。
  • 使用Quarkus官方PanacheMock工具:Quarkus提供PanacheMock专门用于测试Panache操作,可拦截静态方法调用,示例:
@Test
void testTransactionOperation() {
    PanacheMock.mock(User.class);
    when(User.persist(any(User.class))).thenReturn(Uni.createFrom().voidItem());

    Uni<Auth> result = userService.createUser(new User("test"));
    
    verify(User.class).persist(any(User.class));
    assertEquals("test", result.await().indefinitely().getUsername());
}

注意:使用PanacheMock时,测试方法必须在Vert.x上下文运行,需配合@QuarkusTest或@VertxTest。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 04:57:37