1. 程式人生 > >使用DbUnit進行資料庫操作的單元測試

使用DbUnit進行資料庫操作的單元測試

1.DbUnit是junit的擴充套件,主要針對Dao層對資料庫操作的單元測試,可以在不改變資料庫原始資料的情況下,進行測試。

好了,廢話不多說了,其它內容麻煩自己去科普,直接上程式碼:

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>

不喜勿噴,有不對的地方請指出,以便及時更正。

相關推薦

使用DbUnit進行資料庫操作單元測試

1.DbUnit是junit的擴充套件,主要針對Dao層對資料庫操作的單元測試,可以在不改變資料庫原始資料的情況下,進行測試。 好了,廢話不多說了,其它內容麻煩自己去科普,直接上程式碼: 2.直接繼承 DatabaseTestCase 或 DBTestCase 進行測試

Codeigniter 如何在自己的類中進行資料庫操作

自己寫了一個類,放在 libraries 下,但是類裡面不能使用 new mysqli()。因此,使用下面的方法來操作資料庫: 在 application/config/autoload.php 中增加: $autoload['libraries'] = array('datab

採用ADO+ACCESS進行資料庫操作

第一接觸資料庫是2年前在研究生院上課的時候,北京理工大學的一個老太太講的。不是太好!選課失敗!今天做的東西中有根資料庫相關的部分,於是便學了一下,最終決定採用ADO方式防衛ACCESS。 感謝W.C.Y, Z.W.J, W.S.F在這個過程中給與的指導和討論! (1) 動態建立資料庫 boo

python 64式: 第20式、sqlalchemy進行資料庫操作與alembic進行資料庫升級

文章目錄編排如下: 1 引言 2 使用sqlalchemy實現資料庫增刪改查 3 使用alembic進行資料庫升級 4 總結 1 引言 sqlalchemy是python專案採用的ORM(物件關係對映),主要用於資料庫相關的操作。 而alembic是與sqlalchemy搭配使用的資料庫升

框架學習(1)——service層,dao層和service實現類進行資料庫操作

最近也是比較忙,也只能忙裡偷閒地抓緊時間接著學習一下技術,自從上次學習了maven之後,越來越對框架產生了興趣,下了好多的spring視屏,聽著老師的建議,最近也萌生了看別人的程式碼進行學習的想法,然後就上了知乎搜了搜優秀的java框架,發現了一個比較感興趣的,

JAVA類獲取mybatis的mapper進行資料庫操作

- 0x00 前言 最近在做專案的專案, 有個功能是從資料庫中讀取一些引數, 專案用的是spring mvc + spring + mybatis, 也就是需要在java類中通過spring獲取mapper. - 0x01

React-如何進行元件的單元測試

什麼是單元測試 一般測試分成幾個型別:單元測試、整合測試、功能測試。整合測試和功能測試不贅述。單元測試是用來對一個模組、一個函式或者一個類來進行正確性檢驗的測試工作,這裡的單元是程式工作的最小工作單位。單元測試應該僅僅依賴輸入,不依賴多餘的環境,如果你的單元測

從零學springboot——使用jdbcTemplate的方式自定義sql進行資料庫操作

引入jdbcTemplate依賴 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-sta

Spring Boot快速入門(五):使用MyBatis(註解形式)進行資料庫操作

新增依賴 新建專案選擇web,MyBatis,MySQL三個依賴 對於已存在的專案可以在bulid.gradle加入,spring boot將會幫你自動配置好 compile('org.springframework.boot:spring-boot-sta

描述使用Mybatis來進行資料庫操作的過程

什麼是Mybatis?維基百科是這樣定義的:Mybatis是一個Java持久化框架,它通過XML描述符或註解把物件與儲存過程或SQL語句關聯起來。通俗點說就是Mybatis是對JPA(Java持久化API,一個Java應用程式介面規範)的實現,是為了簡化資料庫操作過程而衍生出來的產品。 --

dbUtils進行資料庫操作

package cn.itcast.test; import java.sql.SQLException; import java.util.List; import java.util.Map; import org.apache.commons.dbutils.QueryRunner

Spring Boot快速入門(四):使用jpa進行資料庫操作

新增依賴 新建專案選擇web,JPA,MySQL三個依賴 對於已存在的專案可以在bulid.gradle加入,spring boot將會幫你自動配置好 compile('org.springframework.boot:spring-boot-starter

Struts2 攔截器中實現對資料進行資料庫操作

功能需求說明:         用攔截器的方式,攔截以.action結尾的類,同時記錄訪問的action名稱、action的包路徑、action後面帶的引數、操作者的ID、操作者的姓名、等其他資料。 吐槽點: 1.

Spring4託管Hibernate5並利用HibernateTemplate進行資料庫操作

時隔半年,再次釋出配置類的相關Blog,因為左手受傷原因先做一個簡述。 首先利用idea建立一個Spring+SpringMVC+Hibernate專案,注意的是因為我們要完全放棄Hibernate以及SessionFactory配置檔案,所以Hibernate不需勾選配置檔

Xshell5的簡單使用,結合Xftp 4匯入.sql檔案 進行資料庫操作

第一次寫部落格,好緊張。。。。。。 Xshell下載地址    http://rj.baidu.com/soft/detail/15201.html?ald    安裝什麼的就不用多說了吧,網上有教程,很簡單。 我也是第一次使用Xshell,弄了半天,整的有點明白了,只是初

Hibernate使用配置檔案進行資料庫操作

package com.hibtest;import net.sf.hibernate.HibernateException;import net.sf.hibernate.Session;import net.sf.hibernate.SessionFactory;import net.sf.hiberna

簡單的通過shell指令碼接收引數進行資料庫操作

建表sql語句: SET FOREIGN_KEY_CHECKS=0; -- ---------------------------- -- Table structure for `cent_su

java使用jUnit,jMockit,dbunit做DAO層單元測試方法

第一步:準備資料 先在MySQL資料庫中填寫測試資料和期望資料,然後匯出到xml檔案中。 全表匯出:DBUnitHelper.exportTable("t_dp_content_02001", TEST_DATA_FILE); 條件查詢匯出:DBUnitHelper

一個簡單的進行資料庫操作的類,呼叫內部sqlzz函式並加入sql語句即可

import pymysql #簡單封裝一個可以執行sql語句的類 class Mysql_text(object): #定義一個初始化函式用來開啟資料庫連線和建立遊標物件 def __init__(self): self.db

在eclipse中連線資料庫進行資料庫操作時出現空指標異常類java.lang.NullPointerException

java.lang.NullPointerException載入驅動成功!連線資料庫成功!at com.dao.BookDAO.create(BookDAO.java:24)at servlets.Insert_Book_Servlet.doPost(Insert_Book_