0
votes

I'm trying to understand why I cannot rollback transaction if I throw exception in my test?

I'm using Spring 4.1.5 and I'm trying to test my transactions. I've annotated @Transactional my repository and transaction have been rolled back if repository throw exception. Also I've annotated @Transactional my test method and calling several methods from repository work in one transaction. However when I trow exception in test by myself transaction is not rolled back. Why? It looks like it was done by some purpose or do I do something wrong?

    @RunWith(SpringJUnit4ClassRunner.class)
    @TransactionConfiguration(transactionManager = "transactionManager", defaultRollback = false)
    @ContextHierarchy({
            @ContextConfiguration(locations = {
                    "classpath:/META-INF/spring/jpa-persistence-context.xml"})
    })
    @Transactional(propagation = Propagation.REQUIRED, readOnly = false, rollbackFor = RuntimeException.class)
    public class FeaturedGroupRepositoryTest2 {

        @Transactional(propagation = Propagation.REQUIRED, readOnly = false, rollbackFor = RuntimeException.class)
        @Test
        public void testFeaturedGroupDao() {

            FeaturedGroupEntity newFeaturedGroupEntity = new FeaturedGroupEntity();
            FeaturedGroupEntity savedFeaturedGroupEntity = featuredGroupRepository.save(newFeaturedGroupEntity);
            FeaturedGroupEntity foundFeaturedGroupEntity = featuredGroupRepository.findOne(savedFeaturedGroupEntity.getId());
            throw new RuntimeException("test rollback");
    }
}
1

1 Answers

1
votes

Possibly the same issue that @Kieren Dixon had in How to rollback a database transaction when testing services with Spring in JUnit? that you are missing the TransactionalTestExecutionListener annotation on your Junit class:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = TestConfiguration.class)
@TestExecutionListeners({TransactionalTestExecutionListener.class}) 
public class WorkUnitRepoTest {

    @Inject MyRepo repo;

    @Test
    public void test() {
        repo.delete(1);
    }
}

Even though the Spring documentation for 4.1.7 mentions that the listener is active by default, I had to add it manually to work. However the @Transactional is always required on either the class or method level for it to work.

Excerpt Spring Framework 4.1.7.RELEASE:

In the TestContext framework, transactions are managed by the TransactionalTestExecutionListener which is configured by default, even if you do not explicitly declare @TestExecutionListeners on your test class. To enable support for transactions, however, you must configure a PlatformTransactionManager bean in the ApplicationContext that is loaded via @ContextConfiguration semantics (further details are provided below). In addition, you must declare Spring’s @Transactional annotation either at the class or method level for your tests.