Quarkus测试中PanacheEntity未持久化问题求助
解决Quarkus测试中RestEasy请求看不到测试数据的问题
你猜的没错!核心问题就是事务上下文隔离——测试方法里的@Transactional是跑在测试专属的本地事务里,而通过RestEasy发的HTTP请求会触发一个完全独立的应用事务。测试的事务默认会在测试结束后回滚,而且在HTTP请求执行时,测试的事务还处于未提交状态,所以应用端的服务根本看不到你插入的User数据。
下面给你两个可行的解决方案,推荐第一个:
方案1:用Quarkus专属的@TestTransaction注解
Quarkus专门为这种场景提供了io.quarkus.test.TestTransaction注解,它会自动帮你处理事务同步:测试代码里的数据库操作会在HTTP请求发送前提交,测试结束后又自动回滚,完全不会污染测试环境。
修改你的测试方法就行,只需要加一个注解:
@Test @TestTransaction // 关键就是这个注解 public void testWithValidAuthenticationChallenge() { User user = User.builder() .name("admin") .role(Roles.ADMIN) .status(Status.ACTIVE) .password(BCrypt.withDefaults().hashToString(10, "admin".toCharArray())) .email("admin@admin.com") .build(); user.persistAndFlush(); // 现在这个操作会在HTTP请求前提交,服务能查到数据了 given() .when() .contentType(ContentType.JSON) .body(AuthenticationChallenge.builder().email("admin@admin.com").password("admin").build()) .post(url) .then() .statusCode(200) .log() .all(); }
方案2:手动控制事务提交(不推荐,除非特殊场景)
如果你不想用@TestTransaction,也可以手动提交测试事务,但要记得测试结束后清理数据,避免影响其他测试用例:
import jakarta.persistence.EntityManager; import jakarta.inject.Inject; // 先注入EntityManager @Inject EntityManager em; @Test @Transactional public void testWithValidAuthenticationChallenge() { User user = User.builder() .name("admin") .role(Roles.ADMIN) .status(Status.ACTIVE) .password(BCrypt.withDefaults().hashToString(10, "admin".toCharArray())) .email("admin@admin.com") .build(); user.persistAndFlush(); em.getTransaction().commit(); // 手动提交事务,让服务能看到数据 try { given() .when() .contentType(ContentType.JSON) .body(AuthenticationChallenge.builder().email("admin@admin.com").password("admin").build()) .post(url) .then() .statusCode(200) .log() .all(); } finally { // 测试结束后手动清空数据 em.getTransaction().begin(); User.deleteAll(); em.getTransaction().commit(); } }
补充说明
你的@BeforeEach方法用@Transactional没问题,因为它会在每个测试前执行并自动回滚,刚好能清空数据库,不会干扰其他测试。但测试方法里的事务和HTTP请求的事务是完全隔离的,这就是为什么你在测试里能查到数据,服务里却查不到的原因。
内容的提问来源于stack exchange,提问作者khemist92
相关产品推荐
相关产品推荐

