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

Spring Boot 3.4.1集成测试断言错误:懒加载关联无法获取

Spring Boot 3.4.1升级后Test Containers集成测试懒加载AssertionError问题解决

问题描述

将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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 18:23:18