Spring integration test transaction is not rolled back
Writing integration test for spring based application got problem with transaction rollback - data is inserted, but after transaction rolled back, data are still in database table... Spring 3.0.5, JUnit 4.8.2
Integration Test code
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath:/applicationContext.xml" })
@TransactionConfiguration(transactionManager="txManager",defaultRollback=true)
@Transactional
public class GenerateCodeStrategyTest {
@Autowired
@Qualifier(value = "generateCodeStrategy")
private Strategy generateCodeStrategy;
@Test
@Transactional
public void genCodeIntegrationTestCommunicationFailure() {
//generate some parameters
SMPPSession mockedSession = mock(SMPPSession.class);
generateCodeStrategy.setSession(mockedSession);
generateCodeStrategy.sendRequest(params);
final SubscribeInfo subscribeInfo = subscribeDao.getUserByPhone(phone);
assertNotNull(subscribeInfo);
assertEquals(phone, subscribeInfo.getPhone());
assertEquals(Status.BAD_STATUS, subscribeInfo.getStatus());
}
}
In DEBUG mode in logs I can see transaction started and rolled back
INFO: Began transaction (1): transaction manager [org.springframework.jdbc.datasource.DataSourceTransactionManager@1edd9b3]; rollback [true]
[main] DEBUG org.hibernate.SQL - insert into sms_subscribe (phone_cell, status, ts_subscribe, subscription_status, ts_unsubscribe, receiverIdentification, user_id) values (?, ?, ?, ?, ?, ?, ?)
INFO: Rolled back transaction after test execution for test context [[TestContext@1f18cbe testClass = GenerateCodeStrategyTest, locations = array<String>['classpath:/applicationContext.xml'], testInstance = lv.mrb.server.service.GenerateCodeStrategyTest@14f1726, 开发者_开发技巧testMethod = genCodeIntegrationTestCommunicationFailure@GenerateCodeStrategyTest, testException = [null]]]
Maybe someone have idea why this happens ? Thank you for help.
UPDATED: This integration test generate some parameters, then using Mockito mock of the session object is inserted into Strategy service. This mock object is just throwing exception and on this exception in that Strategy service data is saved to database via DAO layer. Then test make request to database via DAO layer and assert saved values.
Data is persisted via Hibernate so basically in my DAO object object is saved that way
final Session currentSession = sessionFactory.getCurrentSession();
currentSession.save(object);
sessionFactory is AnnotationSessionFactoryBean where datasource is c3p0 ComboPooledDataSource class
UPDATE 2 : The problem was with Mysql engine, by default it was MyISAM, so I just needed to switch it to InnoDB and now all works.
The usual problem is that your service layer calls other layers which are also marked as @Transactional
, perhaps even with REQUIRES_NEW
. In that case, the Test listener only has access to the outer transaction, but has no way to roll back the inner transaction.
Often the problem is that there are @Transactional
annotations on the DAO layer. If there are, remove them. There should be no transaction demarcation on the DAO layer.
Try to remove @Transactional
annotation from class level and left it only for specific test methods.
Hope it helps.
精彩评论