Spring Boot 3.4.1集成测试断言错误:懒加载关联无法获取
问题描述
将Spring Boot从3.3.8升级至3.4.1后,基于Test Containers的集成测试出现异常:调用服务获取Book的懒加载关联details时抛出java.lang.AssertionError,提示Unable to evaluate the expression Method threw 'java.lang.AssertionError' exception.。该问题仅出现于集成测试环境,生产环境无异常。
相关代码片段
测试代码
@Test void test1() throws Exception { Optional<Customer> priceCalculationCustomer = customerRepository.findById(CustomerId.builder().customerId("PRICE_MAIN").salesOrg("PRIC").build()); var book = quotationRepository.findByCustomer(priceCalculationCustomer.get()).getFirst(); BookDto requestBody = BookDto.builder() .bookId(book.getId()) .build(); mvc.perform( MockMvcRequestBuilders.post(BASE_PATH + BOOK_PATH) .contentType(MediaType.APPLICATION_JSON) .content(convertObjectToJsonBytes(requestBody)) .with(jwtRequestPostProcessor)) .andExpect(status().isOk()); }
控制器代码
@PostMapping(value = BOOK_PATH, produces = MediaType.APPLICATION_JSON_VALUE) public void addQuotationDetails(@RequestBody final BookDto bookDto) { addBookDetailService.addBookDto(bookDto); }
服务代码
@Transactional public void addBookDto(BookDto bookDto) { var book = bookFindService.fetchBook(bookDto.getBookId()); book.getDetails().size(); }
Book查询服务代码
public Book fetchBook(long id) { return bookRepository.findById(id) .orElseThrow(() -> new NotFoundProblem( "book %s does not exist.".formatted( id))); }
实体映射
Book实体:
@OneToMany(mappedBy = "book", fetch = FetchType.LAZY, cascade = {CascadeType.ALL}) private List<Detail> details;
Detail实体:
@ManyToOne(optional = false, fetch = FetchType.LAZY) @JoinColumn(name = "id", nullable = false) private Book book;
可能原因及解决方案
1. 事务上下文未覆盖查询操作
addBookDto方法标注了@Transactional,但fetchBook方法未添加事务注解。如果bookFindService是独立Bean,跨Bean调用时事务不会自动继承,导致返回的Book实体处于游离状态,无法触发懒加载。
解决方案:
给fetchBook方法添加只读事务注解,确保查询在事务上下文内执行,实体保持托管状态:
@Transactional(readOnly = true) public Book fetchBook(long id) { return bookRepository.findById(id) .orElseThrow(() -> new NotFoundProblem( "book %s does not exist.".formatted( id))); }
2. Hibernate懒加载配置变更
Spring Boot 3.4.x升级了Hibernate版本(默认到6.5.x),可能调整了hibernate.enable_lazy_load_no_trans的默认值,测试环境下该属性被禁用,导致即使在事务内也无法初始化懒加载代理。
解决方案:
在测试环境配置文件application-test.properties中临时开启该属性(不建议生产环境使用):
spring.jpa.properties.hibernate.enable_lazy_load_no_trans=true
3. Test Containers事务回滚影响实体状态
如果测试类标注了@Transactional,测试结束后事务会回滚,可能导致实体提前脱离托管状态。或者测试数据初始化时,Book与Detail的关联未正确持久化到Test Containers数据库中。
解决方案:
- 若不需要测试后数据回滚,移除测试类上的
@Transactional注解; - 检查测试数据初始化逻辑,确保Book对应的Detail数据已正确插入到Test Containers数据库中。
4. 调试定位具体异常根源
当前错误提示模糊,建议开启Hibernate和Spring事务的调试日志,查看懒加载时的底层异常:
logging.level.org.hibernate=DEBUG logging.level.org.springframework.transaction=DEBUG
通过日志可定位到AssertionError的具体触发点,比如代理类转换异常、EntityManager已关闭等。
5. 检查Spring Boot 3.4.x版本变更
查看Spring Boot 3.4.x发布日志中关于JPA/Hibernate的变更,确认是否有默认配置调整,比如事务管理器行为、懒加载代理机制的变化,针对性调整配置或代码。
总结
优先确保懒加载操作在有效事务上下文内执行,其次排查Spring Boot升级带来的框架配置变化,通过日志调试定位具体异常根源,再针对性解决。
内容的提问来源于stack exchange,提问作者mastach

