如何回滚测试

时间:2012-06-15 13:05:18

标签: java spring

这是我的测试:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath:repositoryContextTest.xml" })
@Transactional
@TransactionConfiguration(defaultRollback = true)
public class SeasonITest {
@Autowired
private SeasonDao seasonDao;

@Test
public void createSeason() throws Exception {
    Season season = new Season();
    season.setName("2012");
    seasonDao.createSeason(season);
}

和我的bean配置文件中的dataSource

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
    destroy-method="close">
    <property name="driverClassName" value="com.mysql.jdbc.Driver" />
    <property name="url" value="jdbc:mysql://localhost/tournament_system" />
    <property name="username" value="root" />
    <property name="password" value="root" />
    <property name="defaultAutoCommit" value="false"/>
    <property name="poolPreparedStatements" value="false"/>
    <property name="maxOpenPreparedStatements" value="0"/>
 </bean>

<bean id="transactionManager"
    class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="dataSource" />
</bean>
<tx:annotation-driven transaction-manager="transactionManager" />

当我运行此测试时,我的数据库中会创建一条新记录。

如何回滚此交易?

这是我看到的日志输出:

2012-06-15 15:00:02,173 [main] INFO  - ionalTestExecutionListener - 
 Rolled back transaction after test execution for test context 
 [[TestContext@76db09 testClass = SeasonITest, 
   locations = array<String>['classpath:repositoryContextTest.xml'], 
   testInstance = org.toursys.repository.dao.SeasonITest@1265109, 
   testMethod = createSeason@SeasonITest, testException = [null]]]

更新

以下所有答案都想改变我不想要的逻辑或数据库引擎。所以我提供的声誉指向了正确的答案:

为什么我这样做:事务配置测试中的@TransactionConfiguration(defaultRollback = true)没有回滚以及如何修复它?

9 个答案:

答案 0 :(得分:7)

如果您使用MySQL和MyISAM引擎,请尝试切换到InnoDB。

对于更复杂的测试,您可能需要一个模拟框架或DB娱乐。

EDIT1: 根据文档,InnoDB是完全ACID支持的事务,而MyISAM支持原子操作。更多阅读:Transaction and Atomic Operation Differences

EDIT2: 在@TransactionConfiguration中,defaultRollback的默认值为true,因此您应该添加@TransactionConfiguration(defaultRollback = false)而不是注释该行

答案 1 :(得分:1)

从表面上看,您的代码和配置看起来是正确的。但是,您可以发布您的SeasonsDAO对象吗?我们首先需要验证SeasonsDAO是否正确配置了交易。

SeasonsDAO需要参与与您的测试用例相同的TransactionContext,并且无法使用您发布的代码进行验证。

您是否将SeasonsDAO标记为@Transactional?

如果不是,我不确定TransactionProxyFactoryBean如何能够代理和声明性地管理事务。

在较高的层面上,spring使用代理的概念来执行许多服务,例如事务管理。

如果您将某些内容标记为@Transactional,Spring将动态创建一个代理,该代理将实现与目标类相同的接口。代理之后,事务拦截器会将方法调用包装到目标类,并根据您指定的默认值或规则决定是回滚还是提交。

答案 2 :(得分:0)

还有其他解决方案:

  1. 使用模拟框架(即Mockito)来模拟数据源。这样您只会测试DAO逻辑
  2. 使用单独的数据库进行测试,可以为每个测试设置。您可以使用DBUnit执行此操作。
  3. 使用内存数据库(即HSQL),因此更改不会持久。
  4. 这样您就不必回滚更改了。

答案 3 :(得分:0)

请确保您必须声明:

<tx:annotation-driven transaction-manager="transactionManager" /> 
你的弹簧配置文件中的

,例如(applicationContext.xml中)。

正如@Lieber已经解释过但更多的解释是:MySQL Server(版本3.23-max和所有版本4.0及更高版本)支持与InnoDB事务存储引擎的事务。 InnoDB提供完整的ACID合规性。请参见第14章,存储引擎。有关InnoDB与标准SQL在处理事务错误方面的差异的信息,请参见第14.3.13节“InnoDB错误处理”。

MySQL服务器中的其他非事务性存储引擎(例如MyISAM)遵循称为“原子操作”的数据完整性的不同范例。在事务方面,MyISAM表实际上始终以autocommit = 1模式运行。原子操作通常提供相当的完整性和更高的性能。因此,MyISAM事务存储引擎始终自动提交事务。

答案 4 :(得分:0)

尝试使用@Transactional

注释测试方法

答案 5 :(得分:0)

哈哈,就像3天前发生在我身上一样。尝试添加transactionManager =&#34; transactionManager&#34;到@contextConfiguration:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:PersistenceHelper-context.xml"})
@TransactionConfiguration(defaultRollback = true, transactionManager = "transactionManager")
@Transactional

另外,我对此并非100%肯定,但您的XML文件应遵循&#34; * - context&#34;格式。如果您想查看我的PersistenceHelper-context.xml文件,请告诉我。

答案 6 :(得分:0)

  • 尝试扩展AbstractTransactionalJUnit4SpringContextTests
  • 请注意,MySql MYISAM表不是事务性的,您需要使用INNODB类型表(请参阅herehere
  • 您的DAO是否也标有@Transactional?这可能会导致问题(请参阅here

答案 7 :(得分:0)

在测试用例逻辑之后尝试使用以下方法。

TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();

答案 8 :(得分:0)

您的Dao需要标记为@Transactional。

还用以下内容注释您的测试:

@TestExecutionListeners(TransactionalTestExecutionListener.class)  //Rolls back transactions by default