我在Spring中使用JPA并在测试中保存实体。在编写测试以验证实体与另一个实体的关系是否正确设置的过程中,我遇到了一个我经常遇到的问题。我有一个测试方法(设置为回滚):
问题在于,当我查看Hibernate日志时,我只看到数据库的单个插入,我希望看到插入然后选择。
我知道这是因为Hibernate试图节省我一些时间,并且知道它有一个带有ID的实体我试图检索但是绕过了一个重要的步骤:我想要确保实体实际上使它成为数据库并且看起来像我认为的那样。什么是解决这个问题的最佳方法,以便我可以测试该实体实际上是在数据库中?
注意:我认为这涉及以某种方式分离实体或告诉Hibernate清除其缓存但我不确定当我有权访问的是JpaRepository对象时如何做到这一点。
一些代码:
public interface UserRepository extends JpaRepository<User, Long> {
//...
}
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = JpaConfig.class, // JpaConfig just loads our config stuff
loader = AnnotationConfigContextLoader.class)
@TransactionConfiguration(defaultRollback = true)
public class UserRepositoryTest {
@Test
@Transactional
public void testRoles() {
User user = new User("name", "email@email.com");
// eventually more here to test entity-to-entity relationship
User savedUser = userRepository.save(user);
userRepository.flush();
savedUser = userRepository.findOne(savedUser.getId());
Assert.assertNotNull(savedUser);
// more validation here
}
}
答案 0 :(得分:1)
您基本上想要测试Hibernate的功能而不是您自己的代码。我的第一个建议是:不要这样做!它已经过多次测试和验证。
如果你真的想测试它,有几个选择:
SessionFactory.getCurrentSession()
,您将获得与存储库使用的季节相同的季节。这样你就可以驱逐对象。答案 1 :(得分:1)
您有两种策略:
对于(1),您可以更改测试以扩展以下Spring类,除了在每个测试的开始/结束时自动开始/回滚事务之外,还将允许您访问可以使用的Spring JdbcTemplate发出本机SQL。
对于(2),您可以通过执行以下操作来清除持久性上下文(将EntityManagerFactory注入到您的测试中:
EntityManagerFactoryUtils.getTransactionalEntityManager(entityManagerFactory).clear();
请参阅我通常使用的以下基本测试类并演示上述内容,并允许在每次测试之前使用已知数据填充数据库(通过DBUnit)。
(事实上在上面我实际上是通过注入一个数据源创建一个新的JdbcTemplate。不记得为什么......)