Search code examples
springjunitspring-transactionsspring-test

Testing @TransactionalEvents and @Rollback


I've been trying to test out @TransactionalEvents (a feature of Spring 4.2 https://spring.io/blog/2015/02/11/better-application-events-in-spring-framework-4-2) with our existing Spring JUnit Tests (run via either @TransactionalTestExecutionListener or subclassing AbstractTransactionalUnit4SpringContextTests but, it seems like there's a forced choice -- either run the test without a @Rollback annotation, or the events don't fire. Has anyone come across a good way to test @TransactionalEvents while being able to @Rollback tests?


Solution

  • Stéphane Nicoll is correct: if the TransactionPhase for your @TransactionalEventListener is set to AFTER_COMMIT, then having a transactional test with automatic rollback semantics doesn't make any sense because the event will never get fired.

    In other words, there is no way to have an event fired after a transaction is committed if that transaction is never committed.

    So if you really want the event to be fired, you have to let the transaction be committed (e.g., by annotating your test method with @Commit). To clean up after the commit, you should be able to use @Sql in isolated mode to execute cleanup scripts after the transaction has committed. For example, something like the following (untested code) might work for you:

    @Transactional
    @Commit
    @Sql(scripts = "/cleanup.sql", executionPhase = AFTER_TEST_METHOD,
         config = @SqlConfig(transactionMode = TransactionMode.ISOLATED))
    @Test
    public void test() { /* ... */ }
    

    Regards,

    Sam (author of the Spring TestContext Framework)