How to rollback nested transactions with Propagation.REQUIRES_NEW in integration tests

esaj picture esaj · Mar 3, 2011 · Viewed 8.3k times · Source

I have several integration tests for various services that extend the following baseclass:

@ContextConfiguration(locations="classpath:applicationContext-test.xml")
@TransactionConfiguration(transactionManager="txManager", defaultRollback=true)
@Transactional
public abstract class IntegrationTestBase extends AbstractTransactionalJUnit4SpringContextTests
{
    //Some setup, filling test data to a HSQLDB-database etc
}

For most cases this works fine, but I have a service class which has transactions defined with propagation=Propagation.REQUIRES_NEW. It seems these transactions are not rolled back (because they are nested transactions and apparently commit within the "outer" transaction?). The "outer" (test-case level) transaction is rolled back, at least according to test logs. The committed transactions mess up some later tests, because they have changed the test data.

I can get around this by forcing the test to re-create and re-populate the database between tests, but my question is, is this expected behavior or am I doing something wrong in my tests? Can the nested transaction be forced to rollback from the testing code?

Answer

JB Nizet picture JB Nizet · Mar 3, 2011

This is expected behaviour, and is one of the main reasons to use REQUIRES_NEW :

  • be able to rollback the new transaction, but commit the outer one
  • be able to commit the new transaction, but rollback the outer one

re-populate the database between tests is probably the best solution, and I would use this solution for all the tests: this allows tests to check that everything works correctly, including the commit (which could fail due to flushing, deferred constraints, etc.).

But it you really want to rollback the transaction, a solution would be to add a boolean argument rollbackAtTheEnd to your service, and rollback the transaction if this argument is true.