如果希望业务类也支持事务处理可以加入以下配置,否则可以略过:
<bean id="accountManagerTarget" class="com.wang.dbunit.AccountManager">
<property name="sqlMapClient" ref="sqlMapClient"/>
</bean>
<bean id="accountManager" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="proxyInterfaces">
<value>
com.wang.dbunit.IAccountManager
</value>
</property>
<property name="interceptorNames">
<list>
<idref local="transactionInterceptor" />
<idref local="accountManagerTarget" />
</list>
</property>
</bean>
以上配置只作用于使业务类,因为我们的测试用例类“HelloDBUnit.java”没有出现在配置文件中,更没有设置任何拦截器,所以测试用例对数据库的所有操作(插入、清除测试数据)目前都不在拦截范围。我们必须在测试用例中手工为它加入事务处理,才可以达到我们的目的。
添加事务管理代码
添加以下属性和方法:
private TransactionStatus ts = null;
private DataSourceTransactionManager transactionManager = null;
......
protected void setUpTransaction()
{
transactionManager
=(DataSourceTransactionManager)context.getBean(
"transactionManager");
TransactionDefinition td = new DefaultTransactionDefinition();
ts = transactionManager.getTransaction(td);
}
protected void tearDownTransaction(boolean commit)
{
if(commit)
{
transactionManager.commit(ts);
}
else
{
transactionManager.rollback(ts);
}
}
修改setUp和tearDown方法:
protected void setUp() throws Exception
{
setUpTransaction();
DataSourced ataSource = getDataSource();
// 替换 Connection connection = dataSource.getConnection();
Connection connection = DataSourceUtils.getConnection(dataSource);
IDatabaseConnection dbUnitCon
= new DatabaseConnection(connection, "SYSTEM");
if(getDataSet()!= null)
{
try
{
getSetUpOperation().execute(dbUnitCon, getDataSet());
}
finally
{
if(connection!= null)
{
// 替换 connection.close();
DataSourceUtils.releaseConnection(
connection, dataSource);
}
}
}
}
protected void tearDown() throws Exception
{
DataSource dataSource = getDataSource();
// 替换 Connection connection = dataSource.getConnection();
Connection connection = DataSourceUtils.getConnection(dataSource);
IDatabaseConnection dbUnitCon
= new DatabaseConnection(connection, "SYSTEM");
if(getDataSet() != null)
{
try
{
// 如果不希望回滚数据,传入 true 参数。
tearDownTransaction(false);
getTearDownOperation().execute(dbUnitCon, getDataSet());
}
finally
{
if(connection!= null)
{
// 替换 connection.close();
DataSourceUtils.releaseConnection(
connection, dataSource);
}
}
}
}
后修改getTearDownOperation,用 DELETE 替换 DELETE_ALL:
protected DatabaseOperation getTearDownOperation() throws Exception
{
return DatabaseOperation.DELETE;
}
现在在表中随便添加一些记录,然后执行我们的测试用例,执行完后,手工添加的数据没有受到任何影响。
后一点提示
因为每一个 testXxx 方法时都会初始化一个测试用例,所以每执行一次 testXxxx 方法都会导致 setUp 和 tearDown 方法被调用一次,而本例的事务定义也都由 setUp 开始, tearDown 结束,也意味着不同测试方法(同一测试用例)之间处于不同的事务范围,导致数据操作结果无法共享(如果每次 tearDown 都回滚数据)。比如在 testInsert 方法中插入数据,在 testSelect 无法获得。要解决这个问题,要适当的修改对 setUpTransaction 和 dearDownTransaction 的调用,使得事务可以在全局范围内被多个 test 方法共享。
E:workpm2_v1_00 est.xml:171: org.dbunit.dataset.NoSuchTableException: VERSION_INFO
DBunit 要求schema 大写google_protectAndRun("render_ads.js::google_render_ad", google_handleError, google_render_ad);