I have no problem testing my DAO and services, but when I test INSERT
s or UPDATE
s 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?
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.
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.
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.
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 ... ); }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With