使用spring和hibernate进行非事务性单元测试



嗨,我有一个单元测试,它应该测试cronjob

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "file:WebContent/WEB-INF/applicationContext.xml" })
@TransactionConfiguration(transactionManager = "hibernateTransactionManager")
@Transactional
public class cronTest {}

但是由于事务的原因,cronjob没有看到测试的数据。但当我删除@Transactional Hibernate时,它会说:

org.hibernate.HibernateException: No Session found for current thread

当我通过自己的提交时

sessionFactory.getCurrentSession().getTransaction().commit();
sessionFactory.getCurrentSession().beginTransaction();

测试在结束时失败

org.springframework.transaction.TransactionSystemException: Could not commit Hibernate transaction; nested exception is org.hibernate.TransactionException: Transaction not successfully started

如何在没有事务的情况下获得单元测试?

测试的结果是这样的:

userDao.clear();
loadeduser = userService.getUserById(createUser.getUserID());
assertTrue(loadeduser.getAuthoritiesEntities().contains(adminRole));
assertTrue(loadeduser.getAuthoritiesEntities().contains(userRole));
// Wait for auto unsign
TestUtils.sleep(10000);
userDao.clear();
loadeduser = userService.getUserById(createUser.getUserID());
assertFalse(loadeduser.getAuthoritiesEntities().contains(adminRole));
assertTrue(loadeduser.getAuthoritiesEntities().contains(userRole));

它检查过期角色的自动取消签名是否有效,石英作业每5秒运行一次

通常,我建议对可以在单个事务中测试的代码使用单元测试,并使用集成测试(启动整个系统并执行您想要测试的序列)来测试多事务行为。

但要回答这个问题:解决这个问题的一种方法是像你所做的那样从测试方法中删除@Transaction,但不是让测试方法直接控制事务,而是允许你正在测试的方法开始/提交他们自己的事务(他们通常都会这样做,对吧?)

例如,我们可能有通过正常DAO工作流运行的测试,并且每个DAO方法都标记为@Transactional。每个方法都控制自己的事务提交,因此我们可以在单个测试方法中测试多事务行为。这个测试可能看起来像这样:

// no @Transactional here, dao methods are @Transactional
public void testMultiTransactionUpdate() {
Entity t = dao.getEntity(id);
t.setProperty("somethingnew");
dao.update(t);
Entity t2 = dao.getEntity(id);
Assert.assertEquals(t1.getProperty(), t2.getProperty());
}

需要注意的一点是,如果您对内存中的数据库(如HSQLDB)进行提交,则在一个测试中所做的更改将不会自动回滚,并且通常对后续测试可见。在测试结束时,您必须手动撤消所有更改,或者确保测试数据不会干扰其他测试,这并不容易。这就是为什么我会谨慎地使用这种技术。

最新更新