我正在使用 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
在我的测试课上。然而问题是我丢失了应用程序代码上的事务,即每次测试后事务都会回滚,但是如果应用程序代码中发生异常,则插入不会回滚并且我的单元测试失败,因为我希望表是空的,但它不是。
我将如何实现这两个级别的事务?是否可以?我可以通过为单元测试编写一个设置方法来解决这个问题,该方法在每次测试之前清除所有表。我对此很满意,但我认为能够使用回滚方法来实现相同的目标会很好。
最佳答案
正如评论部分中所发布的,问题在于,通过使测试方法封装事务,只有在测试抛出异常时才会发生回滚。这使得在抛出异常之前无法验证被测行为。我采用的方法是清空设置方法中的所有表(在每次测试之前)。
关于java - 是否可以编写测试事务代码的事务单元测试?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21493560/