Spring集成测试事务未回滚
为基于 Spring 的应用程序编写集成测试遇到事务回滚问题 - 数据已插入,但事务回滚后,数据仍在数据库表中...... Spring 3.0.5,JUnit 4.8.2
集成测试代码
@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());
}
}
在日志中的调试模式下,我可以看到事务已启动并回滚
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]]]
也许有人知道为什么会发生这种情况?谢谢你的帮助。
更新: 该集成测试生成一些参数,然后使用会话对象的 Mockito 模拟插入到策略服务中。这个模拟对象只是抛出异常,并且在该异常中策略服务数据通过 DAO 层保存到数据库。然后测试通过 DAO 层向数据库发出请求并断言保存的值。
数据是通过Hibernate保存的,所以基本上在我的DAO对象中,对象是以这种方式保存的:
final Session currentSession = sessionFactory.getCurrentSession();
currentSession.save(object);
sessionFactory是AnnotationSessionFactoryBean,其中数据源是c3p0 ComboPooledDataSource类
更新2:问题出在Mysql引擎上,默认情况下它是MyISAM,所以我只需要把它切换到InnoDB现在一切正常了。
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.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
通常的问题是您的服务层调用其他也标记为 @Transactional 的层,甚至可能使用
REQUIRES_NEW
标记。在这种情况下,测试侦听器只能访问外部事务,但无法回滚内部事务。通常的问题是 DAO 层上有
@Transactional
注释。如果有,请将其删除。 DAO 层不应该有事务划分。The usual problem is that your service layer calls other layers which are also marked as
@Transactional
, perhaps even withREQUIRES_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.尝试从类级别删除
@Transactional
注释,并将其仅用于特定的测试方法。希望有帮助。
Try to remove
@Transactional
annotation from class level and left it only for specific test methods.Hope it helps.