Spring集成测试事务未回滚

4

为基于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());
  }
}

在DEBUG模式下,日志中可以看到事务已经开始并回滚。
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,现在一切正常。


你能提供一下你的测试定义吗? - Matej Tymes
2个回答

5

通常的问题是您的服务层调用其他标记为@Transactional的层,甚至可能使用REQUIRES_NEW,在这种情况下,测试监听器仅能访问外部事务,但无法回滚内部事务。

通常的问题是DAO层上有@Transactional注释。如果有,请将其删除。DAO层上不应该有事务划分。


我在DAO层中使用了@Transactional注解,所以我将它们全部删除了(现在我在服务层上使用@Transactional - 在我的情况下是sendRequest服务方法和上述的集成测试中也有),但是测试运行成功后数据仍然存在于数据库中。 - artjomka
1
@aartjomka a) 好的,你的服务层中有REQUIRES_NEW吗?如果有,它可能无法正常工作。b) 你是如何持久化数据的?使用Hibernate、JPA、JDBC吗?或者你在DAO中手动提交数据了吗? - Sean Patrick Floyd
a) 在服务层中,我有默认的传播值(REQUIRED) b) 数据通过Hibernate持久化,dao使用sessionFactory来保存对象(在问题中已更新)。谢谢你帮我解决这个问题。 - artjomka

0
尝试将类级别的@Transactional注解移除,仅在特定的测试方法中保留它。
希望对你有所帮助。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接