繁体   English   中英

与其他启用了事务的集成测试一起运行时,集成测试失败

[英]An integration test fails when running with other integration tests which have transactional enabled

我遇到了一个测试多个服务的集成测试的问题。 我不得不禁用事务以使测试工作而没有任何与事务相关的运行时错误。 集成测试在单独运行时工作正常但在与其他启用了事务的测试一起运行时,会产生此运行时错误:

Running 48 integration tests... 43 of 48
Failure:  Tests the happy case flow of MyService.(MyServiceSpec)
org.springframework.transaction.HeuristicCompletionException: Heuristic completion: outcome state is rolled back; nested exception is org.springframework.transaction.UnexpectedRollbackException: Transaction rolled back because it has bee
n marked as rollback-only
Caused by: org.springframework.transaction.UnexpectedRollbackException: Transaction rolled back because it has been marked as rollback-only
        ... 4 more
Completed 43 integration tests, 1 failed in 0m 32s

我得出结论,运行时发生的原因是因为使用事务的其他集成测试,因为我通过成功运行所有禁用事务的测试来测试它; 在使用事务启用的单个集成测试运行测试时失败。

如何在Grails中混合事务和非事务集成测试?

平台详情:

Grails-2.3.6 Windows 7 64位。 JDK v6。

使用Grails 2.4.3进入这个并且在一堆调试之后看到org.springframework.orm.hiberante4.HibernateTransactionManager.doGetTransaction()它调用TransactionSynchronizationManager.getResource(getSessionFactory())并且如果有其他测试启用了事务,那么它会找到一个线程绑定的SessionHolder,其rollbackOnly设置为true(因为之前的测试已回滚)。 因此,第一次尝试提交事务时,它会看到这个并给出你指出的UnexpectedRollbackException

通过将以下内容放在标记为非事务性的测试的setUp()中,我解决了这个问题:

Holders.grailsApplication.mainContext.getBeansOfType(SessionFactory.class).each { beanName, sessionFactory ->

    SessionHolder sessionHolder = TransactionSynchronizationManager.getResource(sessionFactory)

    if (sessionHolder) {
         sessionHolder.clear()
    }
}

集成测试将执行以下操作

  • 开始交易
  • 运行测试
  • 回滚事务

通常,这将工作并将数据库状态重置为测试之前的状态。 但是,如果您的测试逻辑将以特定方式处理事务,那么您将遇到问题。 一个例子是使用propagation = REQUIRES_NEW在测试代码中创建自己的事务。 无论您在该事务中执行了什么操作,都无法通过测试逻辑回滚。

通常这样的代码会打破测试之间的独立性。 唯一真正安全的方法是让每个测试以空数据库开始并插入所需的内容......

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM