Spring Boot集成测试中数据无法持久化/访问的问题排查
Spring Boot GraphQL集成测试:TestEntityManager保存的数据无法被仓库查询到
问题原因
测试类添加的@Transactional注解会让整个测试方法运行在单一事务上下文中:TestEntityManager.persistFlushFind()保存的数据仅存在于当前事务的缓存里,并未真正提交到数据库。而HttpGraphQlTester发送的GraphQL请求会触发独立的HTTP调用,这个调用会在全新的事务中执行——由于测试事务未提交,新事务无法读取到未提交的数据,因此仓库查询返回空。
解决方案
提供两种可行修复方案:
方案1:移除@Transactional,手动提交事务
移除测试类的事务注解,通过EntityManager手动提交数据,确保数据写入数据库后再发起GraphQL请求:
@SpringBootTest @AutoConfigureHttpGraphQlTester @AutoConfigureTestEntityManager // 移除@Transactional注解 public class BackboneTreeControllerTest { @Autowired HttpGraphQlTester tester; @Autowired private TestEntityManager testEntityManager; @Autowired private EntityManager entityManager; @Test void findTaxon() { Taxon taxon = Taxon.builder() .path(Arrays.asList("path", "to", "taxon")) .nameCanonical("Cocos nucifera") .authorship("Me") .extinct(false) .numDescendants(1L) .numOccurrences(1L) .build(); Taxon savedTaxon = testEntityManager.persistFlushFind(taxon); // 手动提交事务,将数据写入数据库 entityManager.getTransaction().commit(); this.tester.documentName("queries") .operationName("FindTaxon") .variable("taxonId", savedTaxon.getId()) .execute() .path("findTaxon.authorship") .entity(String.class) .isEqualTo("Me"); } }
方案2:保留@Transactional,添加@Commit强制提交
保留事务注解,通过@Commit让测试事务在保存数据后直接提交,后续GraphQL请求即可读取到数据:
@SpringBootTest @AutoConfigureHttpGraphQlTester @AutoConfigureTestEntityManager @Transactional @Commit // 添加该注解,强制提交测试事务 public class BackboneTreeControllerTest { @Autowired HttpGraphQlTester tester; @Autowired private TestEntityManager testEntityManager; @Test void findTaxon() { Taxon taxon = Taxon.builder() .path(Arrays.asList("path", "to", "taxon")) .nameCanonical("Cocos nucifera") .authorship("Me") .extinct(false) .numDescendants(1L) .numOccurrences(1L) .build(); Taxon savedTaxon = testEntityManager.persistFlushFind(taxon); this.tester.documentName("queries") .operationName("FindTaxon") .variable("taxonId", savedTaxon.getId()) .execute() .path("findTaxon.authorship") .entity(String.class) .isEqualTo("Me"); } }
补充说明
- 手动测试时功能正常,是因为手动操作时数据已被提交到数据库,所有请求都能读取到已提交的数据。
- 若不想污染测试数据库,可在测试方法结束后手动清理数据,或结合
@Rollback(注意@Commit会覆盖@Rollback的默认回滚行为)。
内容的提问来源于stack exchange,提问作者m-podolski
相关产品推荐
相关产品推荐

