Spring Data JPA @DataJpaTest测试问题:一级缓存致字段断言不符
你说得没错,问题核心确实是JPA的一级缓存(EntityManager缓存):执行saveAndFlush后,实体实例会被缓存起来,后续的findById直接读取缓存中的对象,导致name字段还是构造时的"John Doe",而非数据库里的真实值(null)。
下面是两种正确编写测试用例的方法:
方法1:清空一级缓存,强制从数据库查询
注入EntityManager,在保存操作后调用clear()清空缓存,让后续查询重新从数据库加载实体:
@DataJpaTest(showSql = true) class TestUserRepository { @Autowired private UserRepository repository; @Autowired private EntityManager entityManager; @Test public void testCreateUser() { repository.saveAndFlush(new User(101, "John Doe")); // 清空当前EntityManager的一级缓存 entityManager.clear(); final var optional = repository.findById(101L); assertTrue(optional.isPresent()); var user = optional.get(); assertNull(user.getName()); } }
方法2:刷新实体,同步数据库状态
如果不想清空所有缓存,也可以直接刷新已保存的实体,将数据库的最新状态同步到缓存对象:
@DataJpaTest(showSql = true) class TestUserRepository { @Autowired private UserRepository repository; @Autowired private EntityManager entityManager; @Test public void testCreateUser() { var savedUser = repository.saveAndFlush(new User(101, "John Doe")); // 从数据库同步该实体的最新状态 entityManager.refresh(savedUser); assertNull(savedUser.getName()); } }
补充说明
@Column(insertable = false)会让JPA生成INSERT语句时忽略name字段,因此数据库中该字段会以默认值(这里是null)存储。- 一级缓存与当前EntityManager绑定,生命周期跟随事务:
clear()会清空缓存中所有实体,refresh()仅针对单个实体同步数据库状态,可根据测试场景选择。
内容的提问来源于stack exchange,提问作者SetNug
相关产品推荐
相关产品推荐

