Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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?

like image 244
blow Avatar asked Nov 12 '10 16:11

blow


People also ask

How do I rollback a transaction in Spring?

Transaction Rollback. The @Transactional annotation is the metadata that specifies the semantics of the transactions on a method. We have two ways to rollback a transaction: declarative and programmatic. In the declarative approach, we annotate the methods with the @Transactional annotation.

How do I test a rollback transaction?

Annotation Type Rollback@Rollback is a test annotation that is used to indicate whether a test-managed transaction should be rolled back after the test method has completed. Consult the class-level Javadoc for TransactionalTestExecutionListener for an explanation of test-managed transactions.

What is @transactional in Junit?

So what does @Transactional mean if you annotate your test suite with it? Well it means that every test method in your suite is surrounded by an overarching Spring transaction. This transaction will be rolled back at the end of the test method regardless of it's outcome.


1 Answers

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 ... );  }  
like image 99
axtavt Avatar answered Oct 17 '22 15:10

axtavt