一个通用的单元测试框架的思考和设计04-实现篇-自动管理测试数据

上篇文章罗列了整个框架的核心接口,这篇文章将提供IunitExecutionListener的一个实现类-DatasetProviderListener,主要用来将测试数据插入到数据库中,待测试完成后自动删除数据

1.dbunit为核心的db测试

   dbunit是个很好的数据库测试框架,提供了多种准备数据的操作策略来简化测试数据的插入或更新操作,参考http://www.dbunit.org/components.html#deleteall

操作描述
DatabaseOperation.UPDATE 使用准备数据更新现有db中的数据(根据准备数据主键ID值),如果数据库中不存在准备数据中的ID,报错退出
DatabaseOperation.INSERT 将测试数据插入到数据库中,如果数据库中已经有对应id的数据,则报错退出
DatabaseOperation.DELETE 删除数据库中id在准备数据中的记录
DatabaseOperation.DELETE_ALL 删除准备数据中相关的数据库表中的所有数据
DatabaseOperation.TRUNCATE 删除准备数据中相关的数据库表中的所有数据
DatabaseOperation.REFRESH 先根据准备数据中的id查询数据库,如果有对应的记录则更新,若无则插入新记录
DatabaseOperation.CLEAN_INSERT 先做一个DELETE_ALL,然后做一个INSERT操作
DatabaseOperation.NONE 什么也不做处理
我们使用dbunit默认的xml格式来准备数据,在测试运行前使用REFRESH操作来插入数据,测试执行完毕后使用DELETE策略将测试数据删除即可

2.@IUnitDataSet注解

我们的dbunit只对那些需要用到数据库测试的类才加载,这里用这个注解来标识(后期我们可以对这个注解进行扩展,如添加filename和format字段,前者表示测试文件名,后者表示文件格式,比如我们后期可能提供以excel格式来准备测试数据)

3.约定

这里框架默认要求测试类和测试类的准备数据放在同一级目录下,如类的路径为com.crazycoder2010.iunit.AppTest.java则其测试数据文件为com/crazycoder2010/iunit/AppTest.xml框架会自动去加载,同时因为需要链接数据库,因此需要配置数据库的jdbc,username,password等,这里要求程序提供一个iunit.properties文件放置在classpath下

##configuration for dbunit
dbunit.connectionUrl=jdbc:hsqldb:hsql://localhost/
dbunit.driverClass=org.hsqldb.jdbcDriver
dbunit.password=
dbunit.username=sa
dbunit.schema=
4.DatasetProviderListener类的源码

package com.crazycoder2010.iunit;

import java.io.IOException;
import java.util.Properties;

import org.dbunit.IDatabaseTester;
import org.dbunit.JdbcDatabaseTester;
import org.dbunit.PropertiesBasedJdbcDatabaseTester;
import org.dbunit.dataset.IDataSet;
import org.dbunit.dataset.xml.FlatXmlDataSetBuilder;
import org.dbunit.operation.DatabaseOperation;

import com.crazycoder2010.iunit.annotation.IUnitDataSet;

/**
 * 用来加载测试数据到db中
 * 
 * @author Kevin
 * 
 */
public class DatasetProviderListener extends IUnitTestExecuteListenerAdapter {
	private IDatabaseTester databaseTester;
	private boolean handleDataSet = true;//标志位,表示当前测试类是否启用了@IUnitDataset标注,如果没用,不做数据库插入删除操作
	private static final Properties PROPERTIES = new Properties();
	static {
		try {
			PROPERTIES.load(DatasetProviderListener.class
					.getResourceAsStream("/iunit.properties"));
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	private Object testInstance;

	/**
	 * 将Excel中的测试数据插入到数据库中
	 * @throws Exception 
	 * 
	 * @see com.crazycoder2010.iunit.IUnitTestExecuteListenerAdapter#prepareTestInstance(com.crazycoder2010.iunit.TestContext)
	 */
	@Override
	public void prepareTestInstance(TestContext testContext) throws Exception {
		IUnitDataSet dataset = testContext.getTestInstance().getClass().getAnnotation(IUnitDataSet.class);
		if(dataset == null){
			handleDataSet = false;
			return;
		}
		this.testInstance = testContext.getTestInstance();
		databaseTester = new JdbcDatabaseTester(//创建数据库链接对象
				PROPERTIES
						.getProperty(PropertiesBasedJdbcDatabaseTester.DBUNIT_DRIVER_CLASS),
				PROPERTIES
						.getProperty(PropertiesBasedJdbcDatabaseTester.DBUNIT_CONNECTION_URL),
				PROPERTIES
						.getProperty(PropertiesBasedJdbcDatabaseTester.DBUNIT_USERNAME),
				PROPERTIES
						.getProperty(PropertiesBasedJdbcDatabaseTester.DBUNIT_PASSWORD));
	}

	@Override
	public void beforeTest(TestContext testContext) throws Exception {
		if(!handleDataSet){
			return;
		}//测试开始前将数据插入到db
		databaseTester.setDataSet(getDataSet());
		databaseTester.setSetUpOperation(DatabaseOperation.REFRESH);
		databaseTester.onSetup();
	}
        //测试数据文件和测试类之间的‘潜规则’
	protected IDataSet getDataSet() throws Exception {
		String pack = testInstance.getClass().getName() ;
		String filePath = "/"+pack.replaceAll("[.]", "/")+ ".xml";
		return new FlatXmlDataSetBuilder().build(this.getClass().getResourceAsStream(filePath));
	}

	/**
	 * 将文件中准备的测试数据从数据库中清空
	 * 
	 * @throws Exception
	 * @see com.crazycoder2010.iunit.IUnitTestExecuteListenerAdapter#afterTest(com.crazycoder2010.iunit.TestContext)
	 */
	@Override
	public void afterTest(TestContext testContext) throws Exception {
		if(!handleDataSet){
			return;
		}
		databaseTester.setTearDownOperation(DatabaseOperation.DELETE);
		databaseTester.onTearDown();
	}
}




  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值