Spring Data JPA结合Junit编写Repository测试类整体运行时测试失败
问题原因
- 事务配置异常导致测试数据残留
你在测试类上添加的@Transactional(propagation = Propagation.REQUIRES_NEW)覆盖了@DataJpaTest的默认事务规则。@DataJpaTest默认会为每个测试方法创建独立事务,执行完成后自动回滚,不会残留测试数据;但自定义的REQUIRES_NEW级别的事务不受默认回滚规则约束,测试方法执行完成后会直接提交,前一个测试写入的数据会保留在数据库中。 - 主键冲突导致merge未执行插入逻辑
运行整个测试类时,方法名排序靠前的should_store_a_todo会先执行,已经写入了id为1的Todo数据。等到should_find_all_todos执行时,你构造id为1的实体调用entityManager.merge(),merge的默认逻辑是:如果传入实体的主键在数据库中已存在,就执行更新操作,而非插入新数据。再加上持久化上下文缓存未及时刷新,就会出现查询不到对应记录的问题。 - 额外排查点
如果你的Todo实体的id字段标注了@GeneratedValue主键生成策略,手动给id赋值的行为本身不符合规范,持久化提供者会优先使用自动生成的主键值,忽略你手动传入的id,也可能导致数据异常。
解决方案
- 优先选择移除类上的
@Transactional(propagation = Propagation.REQUIRES_NEW)注解,恢复@DataJpaTest的默认事务配置,从根源上避免测试数据残留的问题。 - 如果业务场景确实需要使用
REQUIRES_NEW传播级别,可以做如下调整:- 每个测试方法执行完成后手动清理测试数据,避免数据残留
- 测试实体的主键不要手动赋值,完全依赖
@GeneratedValue策略自动生成 - 调用
entityManager.merge()后显式调用entityManager.flush(),强制将缓存变更刷新到数据库中,避免查询时出现缓存不一致的问题
内容的提问来源于stack exchange,提问作者Abdelouahed
相关产品推荐
相关产品推荐

