【问题标题】:An integration test fails when running with other integration tests which have transactional enabled与启用事务的其他集成测试一起运行时,集成测试失败
【发布时间】:2014-06-02 16:39:40
【问题描述】:

我在测试多个服务的集成测试时遇到问题。我必须禁用事务性才能使测试正常工作,而不会出现任何与事务性相关的运行时错误。集成测试在单独运行时运行良好,但在与启用事务的其他测试一起运行时,会产生以下运行时错误:

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.3.8 中。我的测试是 static transactional = false 并且单独运行良好,但运行整个套件时失败。

标签: grails integration-testing spring-transactions grails-2.3


【解决方案1】:

使用 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()
    }
}

【讨论】:

    【解决方案2】:

    集成测试将执行以下操作

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

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

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

    【讨论】:

      猜你喜欢
      • 2013-11-08
      • 1970-01-01
      • 2017-03-29
      • 1970-01-01
      • 2015-03-20
      • 1970-01-01
      • 2014-09-27
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多