1
  1. 问题是关于如何测试持久实体是否有效。我认为测试 JPA 实体映射是否正确以及一切是否按预期工作是有意义的,特别是对于具有级联属性的 @OneToMany/@ElementCollection/@ManyToMany/@OneToOne 的复杂实体映射(例如 CascadeType.ALL)。并确保满足所有 FK/PK/Unique 约束。

  2. 这是一个普遍的问题。具体部分是关于 Spring 测试框架。您可以在下面的代码中看到,DAO 层正在测试,但是由于测试方法被标记为@Transactional,更改应该被回滚,这里是should而不是must,因为我怎么能确定,更改实际上保存在数据库,可能一切都保存在内存中,因为事务被标记为回滚,所以没有数据真的发送到数据库?

  3. 更重要的是,这个测试失败了,因为 account.getId() 返回 0(id 生成是使用 @SequenceGenerator 完成的),但似乎这个值从未分配到 Account 的 id 字段中。这个测试只有在方法被@Rollback(false)注解时才会通过,所以当然不会发生回滚。

  4. 我是对的,在这种情况下,当使用 @Transactional 进行测试时,所有内容都在内存中(至少在不调用 flush() 之前),因此无法检查数据库约束是否正常工作。

  5. 根据上面的想法,测试实体插入的合适方法是什么,并确保插入完成,然后将所有内容回滚到初始状态,以便运行其他测试?(每次执行测试时清理@Before中的数据库?)

  6. 我不想使用 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
        }
    }
    
4

2 回答 2

2

如果您的约束没有延迟,并且您在调用 save 后刷新会话,所有内容都将写入数据库,并应用约束。然后,您可以执行查询并检查您的实体是否返回。但是,返回的实体将是会话保存在内存中的实体。

当我真的想检查某些东西是否正确持久化时,我通常在一个事务中执行持久化(使用 TransactionTemplate),然后在事务提交后执行查询以验证一切正常。

于 2011-12-24T12:28:59.413 回答
0

您可以组合使用 em.flush() 和 em.clear()。em.flush 上面已经描述过了。em.clear() 将分离上下文当前已知的所有实体。

在此之后,您可以尝试查找最近保存的实体,就像您将它们添加到您的上下文中一样,也就是说,对您的实体进行真正的查找。我在 SO 上发布的问题中有一个例子。

如何在单元测试中可靠地单元测试 JPA 实体的更新

于 2013-10-19T20:15:26.397 回答