【问题标题】:Spring integration test transaction is not rolled backSpring集成测试事务不回滚
【发布时间】:2011-05-09 08:26:35
【问题描述】:

为基于 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,现在一切正常。

【问题讨论】:

  • 您能否提供测试的定义?

标签: java spring transactions integration-testing junit4


【解决方案1】:

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

通常问题是DAO层上有@Transactional注解。如果有,请删除它们。 DAO 层不应该有事务划分。

【讨论】:

  • 我在 DAO 层中有 @Transactional 注释,所以我将它们全部删除(现在我在服务层上有 @Transactional - 在我的情况下它是 sendRequest 服务方法以及上面提到的集成测试),但是测试运行成功后,数据仍在数据库中。
  • @artjomka a) 好的,您的服务层中有 REQUIRES_NEW 吗?如果是这样,它就不能工作 b) 你是如何持久化你的数据的?休眠、JPA、JDBC?您是否可能在 DAO 中的某个位置手动提交数据?
  • a) 在服务层中,我有默认的传播值(必需) b) 数据通过 Hibernate 持久化,dao 使用 sessionFactory 来保存对象(已更新)。感谢您帮助我解决此案。
【解决方案2】:

尝试从类级别删除@Transactional 注释,并将其仅用于特定的测试方法。

希望对你有帮助。

【讨论】:

    猜你喜欢
    • 2011-11-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-07
    • 2017-11-07
    • 2011-03-08
    • 2011-10-04
    • 1970-01-01
    相关资源
    最近更新 更多