Alex Rivera | Logout

How to rollback a database transaction when testing services with Spring in JUnit?

Asked 2010-11-12T16:45:23.357
38

I have no problem testing my DAO and services, but when I test INSERTs or UPDATEs I want to rollback the transaction and not effect my database.

I'm using @Transactional inside my services to manage transactions. I want to know, is it possible to know if a transaction will be fine, but rollback it to prevent altering database?

This is my Test:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:/META-INF/spring.cfg.xml")
@TransactionConfiguration(defaultRollback=true)
public class MyServiceTest extends AbstractJUnit38SpringContextTests  {
    @Autowired
    private MyService myService;

    @BeforeClass
    public static void setUpClass() throws Exception {
    }

    @AfterClass
    public static void tearDownClass() throws Exception {
    }

    @Test
    public void testInsert(){
        long id = myService.addPerson( "JUNIT" );
        assertNotNull( id );
        if( id < 1 ){
            fail();
        }
    }
}

The problem is that this test will fail because transaction was rollbacked, but the insert is OK! If I remove @TransactionConfiguration(defaultRollback=true) then the test pass but a new record will be inserted into database.

@Test
@Transactional
@Rollback(true)
public void testInsert(){
    long id = myService.addPerson( "JUNIT" );
assertNotNull(id);
if( id < 1 ){
        fail();
    }
}

Now can test pass correctly, but rollback is ignored and the record is inserted into the database. I have annotated the method addPerson() inside myService with @Transactional, obviously. Why is the rollback being ignored?

Edit
Report

1 Answer

30

You need to extend transaction boundaries to the boundaries of your test method. You can do it by annotating your test method (or the whole test class) as @Transactional:

@Test 
@Transactional
public void testInsert(){ 
    long id=myService.addPerson("JUNIT"); 
    assertNotNull(id); 
    if(id<1){ 
        fail(); 
    } 
} 

You can also use this approach to ensure that data was correctly written before rollback:

@Autowired SessionFactory sf;

@Test 
@Transactional
public void testInsert(){ 
    myService.addPerson("JUNIT"); 
    sf.getCurrentSession().flush();
    sf.getCurrentSession().doWork( ... check database state ... ); 
} 
answered 2010-11-12T17:05:01.140

Your Answer