I am having a problem with an integration test which tests several services. I had to disable transactional to get the test working without any transactional related runtime errors. The integration test works fine when running it on its own but when running with other tests, which have transactional enabled, it creates this runtime error:
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
I have concluded that the reason the runtime occurs is because of the other integration tests which use transactions, as I tested this by successfully running all tests which have transactional disabled; and was unsuccessful when running the test with a single integration test with transactional enabled.
How can I mix transactional and non-transactional integration tests in Grails?
Platform Details:
Grails-2.3.6 Windows 7 64 bit. JDK v6.
For instance, integration tests could fail due to a lost connection with the database. Or perhaps you're using the same environment for both testing and development; in that case, the developers may push new code without tests, causing the test environment to collapse.
The most common problem I see with integration testing is that most attempts at integration testing do not recognize that people “using” the system have different expectations of the system, and will use the “integrations” differently depending on those expectations and their business needs.
@Transactional spans the transaction for entire test method, so if you use some dao (like in your case) that transaction will be rolledback also, however if some method uses transaction propagation type other than REQUIRED , for example REQUIRED_NEW , call to db can be performed anyway, because REQUIRED_NEW suspends ...
@Transaction annotation for integration testing in Spring Boot.
Ran into this with Grails 2.4.3 and after a bunch of debugging saw that in org.springframework.orm.hiberante4.HibernateTransactionManager.doGetTransaction()
it calls TransactionSynchronizationManager.getResource(getSessionFactory())
and if there were other tests with transactional enabled then it will find a thread-bound SessionHolder with rollbackOnly set to true (since the previous test rolled back). So, the first time it tries to commit a transaction, it will see this and give the UnexpectedRollbackException
you indicated.
I got around this by putting the following in the setUp() of the test that was marked as non-transactional:
Holders.grailsApplication.mainContext.getBeansOfType(SessionFactory.class).each { beanName, sessionFactory ->
SessionHolder sessionHolder = TransactionSynchronizationManager.getResource(sessionFactory)
if (sessionHolder) {
sessionHolder.clear()
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With