如何测试JPA实体插入?

时间:2011-12-24 11:54:40

标签: spring jpa transactional

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

  2. 这是一般性问题。具体部分是关于Spring Testing Framework。您可以在下面的代码中看到DAO层正在测试的地方,但是因为测试方法被标记为 @Transactional ,所以应该回滚,这里应该< / em>而不是必须,因为我可以肯定,这些更改实际上都保存在数据库中,可能一切都保存在内存中,因为事务被标记为回滚,所以没有数据真的被发送到数据库吗?

  3. 更重要的是,此测试失败,因为account.getId()返回0(使用@SequenceGenerator完成id生成),但似乎该值永远不会分配到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
        }
    }
    

2 个答案:

答案 0 :(得分:2)

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

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

答案 1 :(得分:0)

你可以组合em.flush()然后em.clear()。 em.flush已在上面描述过。 em.clear()将分离上下文中当前已知的所有实体。

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

How can I reliably unit test updates of a JPA entity in a unit test