问题是关于如何测试持久实体是否有效。我认为测试 JPA 实体映射是否正确以及一切是否按预期工作是有意义的,特别是对于具有级联属性的 @OneToMany/@ElementCollection/@ManyToMany/@OneToOne 的复杂实体映射(例如 CascadeType.ALL)。并确保满足所有 FK/PK/Unique 约束。
这是一个普遍的问题。具体部分是关于 Spring 测试框架。您可以在下面的代码中看到,DAO 层正在测试,但是由于测试方法被标记为@Transactional,更改应该被回滚,这里是should而不是must,因为我怎么能确定,更改实际上保存在数据库,可能一切都保存在内存中,因为事务被标记为回滚,所以没有数据真的发送到数据库?
更重要的是,这个测试失败了,因为 account.getId() 返回 0(id 生成是使用 @SequenceGenerator 完成的),但似乎这个值从未分配到 Account 的 id 字段中。这个测试只有在方法被@Rollback(false)注解时才会通过,所以当然不会发生回滚。
我是对的,在这种情况下,当使用 @Transactional 进行测试时,所有内容都在内存中(至少在不调用 flush() 之前),因此无法检查数据库约束是否正常工作。
根据上面的想法,测试实体插入的合适方法是什么,并确保插入完成,然后将所有内容回滚到初始状态,以便运行其他测试?(每次执行测试时清理@Before中的数据库?)
我不想使用 DBUnit,使用 Spring 根本没有使用 DBUnit 的意义。
@ContextConfiguration( locations = {...}) @RunWith(SpringJUnit4ClassRunner.class) public abstract class JpaRepositoryTest { } public class JpaAccountRepositoryTest extends JpaRepositoryTest { @Inject private AccountRepository accountRepository; @Inject private Account account; @Test @Transactional public void createAccount() { accountRepository.save(account); assertEquals(1, account.getId()); // this assertion will be failed, until @Rollback(false) is used } }
问问题
433 次
2 回答
2
如果您的约束没有延迟,并且您在调用 save 后刷新会话,所有内容都将写入数据库,并应用约束。然后,您可以执行查询并检查您的实体是否返回。但是,返回的实体将是会话保存在内存中的实体。
当我真的想检查某些东西是否正确持久化时,我通常在一个事务中执行持久化(使用 TransactionTemplate),然后在事务提交后执行查询以验证一切正常。
于 2011-12-24T12:28:59.413 回答
0
您可以组合使用 em.flush() 和 em.clear()。em.flush 上面已经描述过了。em.clear() 将分离上下文当前已知的所有实体。
在此之后,您可以尝试查找最近保存的实体,就像您将它们添加到您的上下文中一样,也就是说,对您的实体进行真正的查找。我在 SO 上发布的问题中有一个例子。
于 2013-10-19T20:15:26.397 回答