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

时间:2012-11-21 09:35:14

标签: spring hibernate unit-testing transactions

嗨,我有一个单元测试应该测试一个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秒运行一次

1 个答案:

答案 0 :(得分:1)

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

但要回答这个问题:解决这个问题的一种方法是从测试方法中删除@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),则在一次测试中所做的更改将不会自动回滚,并且通常对后续测试可见。您必须在测试结束时手动撤消所有更改,或确保您的测试数据不会干扰其他不太容易的测试。这就是我谨慎使用这种技术的原因。