Quarkus Reactive Panache 测试:Panache.withTransaction() 中出现“未找到当前 Vertx 上下文”错误

问题描述 投票:0回答:1

我正在开发一个 Quarkus 项目,其中使用 Hibernate Reactive 和 Panache 进行非阻塞数据库操作。我的服务方法使用 Panache.withTransaction() 在事务内创建用户。

这是服务方法:

public Uni<Auth> createUser(Auth authRequest) {
        User user = new User(authRequest);
        String passwordHash = Password.hash(authRequest.getPassword()).withArgon2().getResult();
        user.setPasswordHash(passwordHash);
        return Panache.withTransaction(() -> PanacheEntityBase.persist(user))
            .onItem().transform(success -> {
                log.info("Successfully created user, email: {}", authRequest.getEmail());
                return authRequest;
            })
                .onFailure(ConstraintViolationException.class)
                .transform(ex -> {
                    log.error("User already exists, email: {}", user.getEmail());
                    throw new AccountDoesNotExistsException(Errors.ACCOUNT_ALREADY_EXISTS + user.getEmail());
                });
    }

这是我的测试用例:

package org.acme.service;

import io.quarkus.hibernate.reactive.panache.Panache;
import io.quarkus.hibernate.reactive.panache.PanacheEntityBase;
import io.quarkus.panache.mock.PanacheMock;
import io.quarkus.test.InjectMock;
import io.quarkus.test.TestReactiveTransaction;
import io.quarkus.test.junit.QuarkusTest;
import io.smallrye.mutiny.CompositeException;
import io.smallrye.mutiny.Uni;
import jakarta.inject.Inject;
import org.acme.entity.User;
import org.acme.model.Auth;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;

import java.io.IOException;
import java.util.concurrent.CompletableFuture;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.mockito.ArgumentMatchers.any;

@QuarkusTest
class AuthServiceTest {

    private Auth authRequest;
    @Inject
    private AuthService authService;

    @BeforeEach
    void setUp() {
        authRequest = new Auth();
        authRequest.setEmail("[email protected]");
        authRequest.setPassword("m)ck!123POwed");
        authRequest.setFirstName("mock first name");
        authRequest.setLastName("mcok last name");
        PanacheMock.mock(User.class);
        PanacheMock.mock(Panache.class);
    }

    @Test
    void givenValidAuthRequest_whenCreateUserCalled_thenReturnAuthResponse() {
        Mockito.when(Panache.withTransaction(any())).thenReturn(Uni.createFrom().item(authRequest));
        Auth authResponse = authService.createUser(authRequest).await().indefinitely();
        assertEquals(authRequest.getEmail(), authResponse.getEmail());
    }

    @Test
    void givenValidAuthRequest_whenCreateUserCalled_thenThrowsException() {
        Mockito.when(User.persist(any(User.class), any(Object.class))).thenReturn(Uni.createFrom().failure(new IOException("Mock exception")));
        assertThrows(CompositeException.class, () -> authService.createUser(authRequest).await().indefinitely());
    }

}

当我运行测试时,遇到以下错误:

No current Vertx context found
java.lang.IllegalStateException: No current Vertx context found
    at io.quarkus.hibernate.reactive.panache.common.runtime.SessionOperations.vertxContext(SessionOperations.java:191)
    at io.quarkus.hibernate.reactive.panache.common.runtime.SessionOperations.withSession(SessionOperations.java:110)
    at io.quarkus.hibernate.reactive.panache.common.runtime.SessionOperations.withTransaction(SessionOperations.java:88)
    at io.quarkus.hibernate.reactive.panache.common.runtime.WithTransactionInterceptor.intercept(WithTransactionInterceptor.java:20)
    at io.quarkus.hibernate.reactive.panache.common.runtime.WithTransactionInterceptor_Bean.intercept(Unknown Source)
    at io.quarkus.arc.impl.InterceptorInvocation.invoke(InterceptorInvocation.java:42)
    at io.quarkus.arc.impl.AroundInvokeInvocationContext.perform(AroundInvokeInvocationContext.java:30)
    at io.quarkus.arc.impl.InvocationContexts.performAroundInvoke(InvocationContexts.java:27)
    at org.acme.service.AuthService_Subclass.createUser(Unknown Source)
    at org.acme.service.AuthService_ClientProxy.createUser(Unknown Source)
    at org.acme.service.AuthServiceTest.givenValidAuthRequest_whenCreateUserCalled_thenReturnAuthResponse(AuthServiceTest.java:46)
    at java.base/java.lang.reflect.Method.invoke(Method.java:580)
    at io.quarkus.test.junit.QuarkusTestExtension.runExtensionMethod(QuarkusTestExtension.java:973)
    at io.quarkus.test.junit.QuarkusTestExtension.interceptTestMethod(QuarkusTestExtension.java:823)
    at java.base/java.util.ArrayList.forEach(ArrayList.java:1596)
    at java.base/java.util.ArrayList.forEach(ArrayList.java:1596)

我尝试过的:

  • 模拟 Panache.withTransaction() 返回一个 Uni
  • 模拟 User.persist()。
  • 尝试不同的模拟变体,但我总是遇到错误“找不到当前 Vertx 上下文”。 我的理解:
  • 这似乎与 Quarkus 的反应式模型以及测试中对 Vert.x 上下文的需求有关。
  • 我相信我在测试环境中没有正确处理 Panache.withTransaction() 的异步行为。

问题:

  • 如何设置测试在正确的 Vert.x 上下文中运行以防止出现此错误?
  • 在 Quarkus 中是否有一种特定的方法可以使用 Panache 来模拟反应操作?
  • 有没有一种替代方法来测试 Panache.withTransaction() 来避免这个问题? 任何帮助或指导将不胜感激!
mockito quarkus quarkus-panache
1个回答
0
投票

您可能缺少

io.quarkus.test.vertx.RunOnVertxContext
注释:

@Test
@RunOnVertxContext
public void givenValidAuthRequest_whenCreateUserCalled_thenReturnAuthResponse() {
  ...
}

您可以查看文档以获取完整示例

© www.soinside.com 2019 - 2024. All rights reserved.