是否可以编写测试事务代码的事务单元测试?

时间:2014-02-01 02:51:22

标签: java spring unit-testing transactions aop

我正在使用Spring编写应用程序。我想把我的JDBC代码写成事务性的,我可以通过使用AOP来实现:

<tx:advice id="txAdvice" transaction-manager="transactionManager">
    <tx:attributes>
        <tx:method name="get*" read-only="true" rollback-for="MyCustomException"/>
        <tx:method name="*" rollback-for="MyCustomException" />
    </tx:attributes>
</tx:advice>

<aop:config>
    <aop:pointcut id="pc" expression="execution(* com.me.jdbc.*.*(..))" />
    <aop:advisor advice-ref="txAdvice" pointcut-ref="pc" />
</aop:config>

<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="dataSource" />
</bean>

<bean id="dataSource" class="org.springframework.jdbc.datasource.TransactionAwareDataSourceProxy">
    <constructor-arg ref="simpleDataSource" />
</bean>

<bean id="simpleDataSource" class="org.springframework.jdbc.datasource.SimpleDriverDataSource">
    <property name="driverClass" value="org.h2.Driver" />
    <property name="username" value="sa" />
    <property name="password" value="" />
    <property name="url" value="jdbc:h2:mem:aas;MODE=Oracle;DB_CLOSE_DELAY=-1;MVCC=true" />
</bean>

因此,如果发生MyCustomException,com.me.jdbc中的所有方法都应该是事务性的和回滚的。到目前为止这是有效的。

我现在想编写一个单元测试,但是我希望我的单元测试是事务性的,这样一旦测试完成,整个事务就会回滚并使数据库保持原样。

我能够通过宣布:

来实现这一目标
@TestExecutionListeners({ DependencyInjectionTestExecutionListener.class, TransactionalTestExecutionListener.class })
@Transactional

在我的Test课上。然而问题是我丢失了应用程序代码上的事务,即在每次测试之后事务被回滚,但是如果应用程序代码中发生异常,则插入不会回滚而我的单元测试失败,因为我希望表格能够是空的,但事实并非如此。

我如何实现这两个级别的交易?可能吗?我可以通过为我的单元测试编写一个设置方法来解决这个问题,该方法在每次测试之前清除所有表。我对此很好,但我认为能够使用回滚方法实现同样的事情会很好。

1 个答案:

答案 0 :(得分:0)

正如评论部分所述,问题在于通过使测试方法封装事务,只有在测试抛出异常时才会发生回滚。这使得在抛出异常之前无法验证测试中的行为。我已经采用了在安装方法中清空所有表的方法(在每次测试之前)。