使用DbUnit进行数据库操作的单元测试

1.DbUnit是junit的扩展,主要针对Dao层对数据库操作的单元测试,可以在不改变数据库原始数据的情况下,进行测试。

官网:http://dbunit.sourceforge.net/

下载地址:http://download.csdn.net/detail/sanfye/8992365

好了,废话不多说了,其它内容麻烦自己去科普,直接上代码:

2.直接继承 DatabaseTestCase 或 DBTestCase 进行测试,注意在项目中不建议这么做,因为它会把测试用例插入到数据库中并把真实数据给删除掉(可能是我的原因,有空了再研究),这只做入门测试使用。

//使用DBUnit进行数据库测试,可以继承自 DBTestCase或DatabaseTestCase(带数据库链接的)
public class UserDaoTest extends DatabaseTestCase{
	
	private IUserDao userDao = new UserDao();

	@Override
	//处理数据链接的,如果是继承自DBTestCase则可以不用实现此方法,数据库的链接可以在构造函数中进行设置
	protected IDatabaseConnection getConnection() throws Exception {
		Class driverClass = Class.forName("com.mysql.jdbc.Driver");
		String url = "jdbc:mysql://localhost:3306/swh_hibernate4" ;
		Connection jdbcConnect = DriverManager.getConnection(url,"root", "root");
		IDatabaseConnection databaseConnection = new DatabaseConnection(jdbcConnect);
		//也可以直接指定数据库进行链接
//		IDatabaseConnection databaseConnection = new MySqlConnection(jdbcConnect, "swh_hibernate4");
		System.out.println("----->1. 进入 getConnection <----------");
		return databaseConnection;
	}

	//
	@Override
	//从XML数据集中读取数据和结构,实例化为IDataSet对象,
	//返回的Idataset代表数据表里面将要存放的数据。
	//该方法会在getSetUpOperation和getTearDownOperation方法执行之后分别执行一次。
	//注意:在getSetUpOperation之后执行 是 填充测试数据,在getTearDownOperation之后执行是为 恢复真实数据 (这两步操作需要自己控制)
	protected IDataSet getDataSet() throws Exception {
		System.out.println("----->3/5. 进入 getDataSet <----------");
		//读取xml文件中的预存数据
	    InputStream is = new FileInputStream("src/test/resources/com/swh/user/dao/t_user.xml");
	    Assert.assertNotNull("dbunit的基本数据文件不存在",is);
	    //从2.4.7之后DBUnit就不推荐使用FlatXmlDataSet()方法了 。
//		IDataSet dataSet = new FlatXmlDataSet(is);
		IDataSet dataSet = new FlatXmlDataSetBuilder().build(is);  
		
		return dataSet;
	}
	 
	@Override
	//可选的覆盖,该方法代表运行该测试用例之前,要作的操作。默认就是CLEAN_INSERT
	//通过覆盖DatabaseTestCase中的getSetUpOperation()方法来实现自己的动作
	protected DatabaseOperation getSetUpOperation() throws Exception {
		System.out.println("----->2. 进入 getSetUpOperation <----------");
		//先清空数据表里的数据,再插入 getDataSet 返回的数据到数据表中,
		// DatabaseOperation.INSERT :是默认操作(也是我们常用的操作) (它首先会将目标数据库中与我们提供的种子文件一致的数据删除,然后将我们提供的数据插入到数据库中。这个实施顺序保证了我们对数据库的精确控制 ) 。
		//DatabaseOperation.NONE: 不做任何事情。
		//DatabaseOperation.REFRESH:通过这个操作,我们可以用种子文件中的数据去更新目标数据库里的数据
		//还有 DatabaseOperation.UPDATE 、  DatabaseOperation.DELETE 、 DatabaseOperation.DELETE_ALL 、 DatabaseOperation.TRUNCATE 、 CompositeOperation 、 TransactionOperation 和 IdentityInsertOperation 等几个状态
		return DatabaseOperation.CLEAN_INSERT ;
	};
	
 
	@Override
	// 可选的覆盖,该方法代表运行完该测试,要做的操作。默认就是NONE 
	protected DatabaseOperation getTearDownOperation() throws Exception {
		System.out.println("----->4. 进入 getTearDownOperation <----------");
		return DatabaseOperation.NONE;
	}
	

	@Test
	public void testAdd(){
		System.out.println("----->进入 testAdd <----------");
		User user = new User();
		user.setUsername("testAdd");
		user.setPassword("456");
		user.setNickname("测试4");
		
		userDao.add(user);
		User user_ = userDao.loadByUserName(user.getUsername());
		
		assertEquals("testAdd",user_.getUsername());
		
	}
	
	@Test
	public void testLoadByUserName(){
		System.out.println("----->进入 testLoadByUserName <----------");
		User user = userDao.loadByUserName("test2");
		assertEquals("测试员2", user.getNickname());
		
	} 

}
执行后数据库中的记录:

3.封装自己的DBUnit测试类或抽象测试类(使用dbunit中提供的方法),主要思路是 备份数据库中真实数据-->清除真实数据并插入测试用例数据-->执行测试用例-->清除测试数据并恢复真实数据;另外,该类也可以继承 DatabaseTestCase 或 DBTestCase 实现其中的方法按照上面的思路进行封装。

/**
 * DBUnit Dao数据库 测试 的抽象类,
 * Dao层方法的测试只需继承此类,
 * 并调用相应的方法即可完成隔离真实数据层的数据测试
 * @author 
 * 2015.08.11
 *
 */
public abstract class AbstractDbUnitTestCase {
	
	//数据库链接
	public static IDatabaseConnection dbunitCon ;
	//备份真实数据的文件
	private File tempFile ; 
	
	@BeforeClass
	//在类执行之前执行,初始化数据库链接
	public static void init() throws DatabaseUnitException{
		 
		dbunitCon = new DatabaseConnection(DbUtil.getConnection());
	}
	
	/**
	 * 构建初始 测试 数据集
	 * @param tname 要构建的数据集的数据文件名 tname.xml
	 * @return 
	 * @throws DataSetException
	 */
	protected IDataSet createDataSet(String tname) {
		//获取预置数据集
		InputStream is = AbstractDbUnitTestCase.class.getResourceAsStream("/com/swh/user/dao/"+tname+".xml");
		
		Assert.assertNotNull("dbunit的基本文件 "+tname+".xml 不存在",is);
		//构建数据集
		IDataSet dataSet = null;
		try {
			dataSet = new FlatXmlDataSetBuilder().build(is);
		} catch (DataSetException e) {
			e.printStackTrace();
		}  
		
		return dataSet ;
	}
	
	
	
	//===========备份真实数据的公共方法==========================================================//
	
	/**
	 * 备份数据表
	 * @param tname
	 * @throws DataSetException
	 * @throws IOException
	 */
	protected void backUpOneTable(String tname) {
		backUpCustomTable(new String[]{tname});
	}
	/**
	 * 同时备份多张表
	 * @param tname
	 * @throws DataSetException
	 * @throws IOException
	 */
	protected void backUpCustomTable(String[] tname) {
		try {
			QueryDataSet queryDataSet = new QueryDataSet(dbunitCon);
			for(String str : tname){
				queryDataSet.addTable(str);
			}
			writeBackUpFile(queryDataSet);
		} catch (Exception e) {
			e.printStackTrace();
		}
		
	}
	
	/**
	 * 备份全部的真实数据表
	 * @author sangwenhao
	 * 2015.08.10
	 */
	protected void backUpAllTable(){
		try {
			IDataSet dataSet = dbunitCon.createDataSet();
			//保存到物理文件
			writeBackUpFile(dataSet);
		} catch (Exception e) {
			e.printStackTrace();
		}
		
	}
	
	/**
	 * 保存临时文件(数据库中真实数据)操作
	 * @param dataSet
	 * @author sangwenhao
	 * 2015.08.11
	 */
	protected void writeBackUpFile(IDataSet dataSet) {
		
		try {
			tempFile = File.createTempFile("back", "xml");
			FlatXmlDataSet.write(dataSet, new FileWriter(tempFile) );
		} catch (IOException e) {
			e.printStackTrace();
		} catch (DataSetException e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * 恢复数据表中的原始数据
	 * @author sangwenhao
	 * 2015.08.10
	 */
	protected void resumeTable() {
		try {
			//读取 备份的真实数据集
			IDataSet ds = new FlatXmlDataSet(new FlatXmlProducer(new InputSource(new FileInputStream(tempFile))));
			//执行 插入数据 操作
			DatabaseOperation.CLEAN_INSERT.execute(dbunitCon, ds);
			
		} catch (Exception e) {
			e.printStackTrace();
		}
		
	}
	
	/**
	 * 销毁链接
	 * @author sangwenhao
	 * 2015.08.10
	 */
	protected void destory() {
		try {
			if(dbunitCon != null) dbunitCon.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
		
	}
}

测试用例的实现方法(注意:测试方法是倒着执行的):

//使用DBUnit进行数据库测试,可以继承自 DBTestCase或DatabaseTestCase(带数据库链接的)
public class UserDaoTest extends DatabaseTestCase{
	
	private IUserDao userDao = new UserDao();

	@Override
	//处理数据链接的,如果是继承自DBTestCase则可以不用实现此方法,数据库的链接可以在构造函数中进行设置
	protected IDatabaseConnection getConnection() throws Exception {
		Class driverClass = Class.forName("com.mysql.jdbc.Driver");
		String url = "jdbc:mysql://localhost:3306/swh_hibernate4" ;
		Connection jdbcConnect = DriverManager.getConnection(url,"root", "root");
		IDatabaseConnection databaseConnection = new DatabaseConnection(jdbcConnect);
		//也可以直接指定数据库进行链接
//		IDatabaseConnection databaseConnection = new MySqlConnection(jdbcConnect, "swh_hibernate4");
		System.out.println("----->1. 进入 getConnection <----------");
		return databaseConnection;
	}

	//
	@Override
	//从XML数据集中读取数据和结构,实例化为IDataSet对象,
	//返回的Idataset代表数据表里面将要存放的数据。
	//该方法会在getSetUpOperation和getTearDownOperation方法执行之后分别执行一次。
	//注意:在getSetUpOperation之后执行 是 填充测试数据,在getTearDownOperation之后执行是为 恢复真实数据 (这两步操作需要自己控制)
	protected IDataSet getDataSet() throws Exception {
		System.out.println("----->3/5. 进入 getDataSet <----------");
		//读取xml文件中的预存数据
	    InputStream is = new FileInputStream("src/test/resources/com/swh/user/dao/t_user.xml");
	    Assert.assertNotNull("dbunit的基本数据文件不存在",is);
	    //从2.4.7之后DBUnit就不推荐使用FlatXmlDataSet()方法了 。
//		IDataSet dataSet = new FlatXmlDataSet(is);
		IDataSet dataSet = new FlatXmlDataSetBuilder().build(is);  
		
		return dataSet;
	}
	 
	@Override
	//可选的覆盖,该方法代表运行该测试用例之前,要作的操作。默认就是CLEAN_INSERT
	//通过覆盖DatabaseTestCase中的getSetUpOperation()方法来实现自己的动作
	protected DatabaseOperation getSetUpOperation() throws Exception {
		System.out.println("----->2. 进入 getSetUpOperation <----------");
		//先清空数据表里的数据,再插入 getDataSet 返回的数据到数据表中,
		// DatabaseOperation.INSERT :是默认操作(也是我们常用的操作) (它首先会将目标数据库中与我们提供的种子文件一致的数据删除,然后将我们提供的数据插入到数据库中。这个实施顺序保证了我们对数据库的精确控制 ) 。
		//DatabaseOperation.NONE: 不做任何事情。
		//DatabaseOperation.REFRESH:通过这个操作,我们可以用种子文件中的数据去更新目标数据库里的数据
		//还有 DatabaseOperation.UPDATE 、  DatabaseOperation.DELETE 、 DatabaseOperation.DELETE_ALL 、 DatabaseOperation.TRUNCATE 、 CompositeOperation 、 TransactionOperation 和 IdentityInsertOperation 等几个状态
		return DatabaseOperation.CLEAN_INSERT ;
	};
	
	@Override
	// 可选的覆盖,该方法代表运行完该测试,要做的操作。默认就是NONE 
	protected DatabaseOperation getTearDownOperation() throws Exception {
		System.out.println("----->4. 进入 getTearDownOperation <----------");
		return DatabaseOperation.NONE;
	}
	@Test
	public void testAdd(){
		System.out.println("----->进入 testAdd <----------");
		User user = new User();
		user.setUsername("testAdd");
		user.setPassword("456");
		user.setNickname("测试4");
		userDao.add(user);
		User user_ = userDao.loadByUserName(user.getUsername());
		assertEquals("testAdd",user_.getUsername());
	}
	@Test
	public void testLoadByUserName(){
		System.out.println("----->进入 testLoadByUserName <----------");
		User user = userDao.loadByUserName("test2");
		assertEquals("测试员2", user.getNickname());
	} 
}



4. xml 数据集文件

<?xml version="1.0" encoding="UTF-8"?>
<!-- 使用DBUnit进行测试的 测试数据 -->
<dataset>
<!-- 标签名应和数据库中表的名称对应;下面标签与数据库中表名:user对应 
	属性名应和数据库中表的字段名称对应。
-->
  <t_user id="1" username="admin" password="123456" nickname="管理员" />
  <t_user id="2" username="test2" password="123456" nickname="测试员2" />
  <t_user id="3" username="test3" password="123" nickname="测试员3" />
</dataset>

不喜勿喷,有不对的地方请指出,以便及时更正。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值