DBUnit使用介绍
一、DbUnit设计理念
熟悉单元测试的开发人员都知道,在对数据库进行单元测试时候,通常采用的方案有运用模拟对象(mock objects)和stubs两种。通过隔离关联的数据库访问类,比如JDBC的相关操作类,来达到对数据库操作的模拟测试。然而某些特殊的系统,比如利 用了EJB的CMP(container-managed persistence)的系统,数据库的访问对象是在最底层而且很隐蔽的,那么这两种解决方案对这些系统就显得力不从心了。
DBUnit的设计理念就是在测试之前,备份数据库,然后给对象数据库植入我们需要的准备数据,最后,在测试完毕后,读入备份数据库,回溯到测试前的状态;而且又因为DBUnit是对JUnit的一种扩展,开发人员可以通过创建测试用例代码,在这些测试用例的生命周期内来对数据库的操作结果进行比较。
二、DbUnit测试基本概念和流程
基于DbUnit 的测试的主要接口是IDataSet。IDataSet代表一个或多个表的数据。
可以将数据库模式的全部内容表示为单个IDataSet 实例。这些表本身由Itable 实例来表示。
IDataSet 的实现有很多,每一个都对应一个不同的数据源或加载机制。最常用的几种 IDataSet实现为:
FlatXmlDataSet:数据的简单平面文件 XML 表示
QueryDataSet:用 SQL 查询获得的数据
DatabaseDataSet:数据库表本身内容的一种表示
XlsDataSet :数据的excel表示
DBUnit支持的数据库包括,db2,h2,hsqldb,mckoi,mssql,mysql,netezza,oralce,postgresql.
三、DBUnit测试流程:
一般而言,使用DbUnit进行单元测试的流程如下:
根据业务,做好测试用的准备数据和预想结果数据,通常准备成xml格式文件。
在setUp()方法里边备份数据库中的关联表。
在setUp()方法里边读入准备数据。
对测试类的对应测试方法进行实装:执行对象方法,把数据库的实际执行结果和预想结果进行比较。
在tearDown()方法里边,把数据库还原到测试前状态。
四、实例开发:
1、新建一个pom工程,加入相关依赖:
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.dbunit</groupId>
<artifactId>dbunit</artifactId>
<version>2.5.</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-nop</artifactId>
<version>1.7.</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.</version>
</dependency>
2、新建工程相关目录

BaseDao.java文件:
public class BaseDao {
    private static Connection CONNECTION_INSTANCE = null;
    protected Connection getConnection() throws Exception{
        if(null==CONNECTION_INSTANCE){
            Class.forName("com.mysql.jdbc.Driver");
            CONNECTION_INSTANCE=DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/test","root","root");
        }
        return CONNECTION_INSTANCE;
    }
    protected void closeConnection() throws Exception{
        if(null!=CONNECTION_INSTANCE){
            if(!CONNECTION_INSTANCE.isClosed()){
                CONNECTION_INSTANCE.close();
            }
            CONNECTION_INSTANCE=null;
        }
    }
}
DBUnitUtils.java文件
public class DBUnitUtils {
    //产生数据集
    public static void generateDatasetDtd(String[] tables) throws Exception{
        QueryDataSet dataSet=new QueryDataSet(DButils.getDataBaseConnection());
        for(String _table:tables){
            dataSet.addTable(_table);
        }
        FlatDtdDataSet.write(dataSet, new FileOutputStream(new File("resource/tmp.dtd")));
        //FlatXmlDataSet.write(dataSet,new FileOutputStream(new File("resource/dbunit1.xml")));
    }
    //备份表数据
    public static void backupDatabase(String[] tables,File backupFile) throws Exception{
        QueryDataSet dataSet=new QueryDataSet(DButils.getDataBaseConnection());
        for(String _table:tables){
            dataSet.addTable(_table);
        }
        FlatXmlDataSet.write(dataSet, new FileOutputStream(backupFile));
    }
    //清空表数据,并导入测试数据
    public static void importTables(File dataFile) throws Exception{
        IDataSet dataSet=new FlatXmlDataSetBuilder().build(dataFile);
        DatabaseOperation.CLEAN_INSERT.execute(DButils.getDataBaseConnection(), dataSet);
    }
    //清空表数据,恢复备份数据
    public static void resumeDatabase(File backupFile) throws Exception{
        IDataSet dataSet=new FlatXmlDataSetBuilder().build(backupFile);
        DatabaseOperation.CLEAN_INSERT.execute(DButils.getDataBaseConnection(), dataSet);
    }
}
DButils.java文件
public class DButils {
    private static IDatabaseConnection conn;
    //通过dbUnit创建数据库连接
    public static IDatabaseConnection getDataBaseConnection() throws ClassNotFoundException, SQLException, DatabaseUnitException{
        if(conn==null){
            Class.forName("com.mysql.jdbc.Driver");
            Connection dbConn=DriverManager.getConnection("jdbc:mysql://localhost:3306/test", "root", "root");
            conn =new MySqlConnection(dbConn,"test");
            return conn;
        }
        return conn;
    }
    //关闭数据库连接
    public static void closeConnection(){
        if(conn!=null){
            try {
                conn.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        conn=null;
    }
}
User.java文件
public class User {
    private long id;
    private String username;
    private String password;
    private String name;
    public long getId() {
        return id;
    }
    public void setId(long id) {
        this.id = id;
    }
    public String getUsername() {
        return username;
    }
    public void setUsername(String username) {
        this.username = username;
    }
    public String getPassword() {
        return password;
    }
    public void setPassword(String password) {
        this.password = password;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
}
UserService.java文件
public interface UserService {
    public long create(User user) throws Exception;
    public void update(User user) throws Exception;
    public User get(Long id) throws Exception;
    public void delete(Long id) throws Exception;
    public List<User> list() throws Exception;
}
UserServiceImpl.java文件
public class UserServiceImpl extends BaseDao implements UserService{
    //新增用户返回主键
    public long create(User user) throws Exception {
        Long id=null;
        PreparedStatement stm=getConnection().prepareStatement("insert into user(username, password, name) values(?, ?, ?)", Statement.RETURN_GENERATED_KEYS);
        stm.setString(, user.getName());
        stm.setString(, user.getPassword());
        stm.setString(, user.getName());
        stm.executeUpdate();
        ResultSet rs=stm.getGeneratedKeys();
        if(rs.first()){
            id=rs.getLong();
        }
        return id;
    }
    //更新用户
    public void update(User user) throws Exception {
        PreparedStatement stm = getConnection().prepareStatement("update user set password = ?, name = ? where username = ?", Statement.RETURN_GENERATED_KEYS);
        stm.setString(, user.getPassword());
        stm.setString(, user.getName());
        stm.setString(, user.getUsername());
        stm.executeUpdate();
        closeConnection();
    }
    //获取用户
    public User get(Long id) throws Exception {
        User user = null;
        PreparedStatement stm = getConnection().prepareStatement("select username, password, name from user where id=?");
        stm.setLong(, id);
        ResultSet rs = stm.executeQuery();
        if (rs.first()) {
            user = new User();
            user.setUsername(rs.getString());
            user.setPassword(rs.getString());
            user.setName(rs.getString());
            user.setId(id);
        }
        closeConnection();
        return user;
    }
    //删除用户
    public void delete(Long id) throws Exception {
        PreparedStatement stm = getConnection().prepareStatement("delete from user where id=?");
        stm.setLong(, id);
        stm.executeUpdate();
        closeConnection();
    }
    //返回所有用户列表
    public List<User> list() throws Exception {
        List<User> users = new ArrayList<User>();
        PreparedStatement stm = getConnection().prepareStatement("select username, password, name, id from user");
        ResultSet rs = stm.executeQuery();
        while (rs.next()) {
            User user = new User();
            user.setUsername(rs.getString());
            user.setPassword(rs.getString());
            user.setName(rs.getString());
            user.setId(rs.getLong());
            users.add(user);
        }
        closeConnection();
        return users;
    }
}
UserServiceDBTestCase.java文件
public class UserServiceDBTestCase extends DatabaseTestCase{
    private UserService userService;
    @Override
    //新建一个userDao对象
    protected void setUp() throws Exception {
        super.setUp();
        userService = new UserServiceImpl();
    }
    @Override
    //清空userDao对象
    protected void tearDown() throws Exception {
        super.tearDown();
        userService = null;
    }
    @Override
    //获取数据库连接
    protected IDatabaseConnection getConnection() throws Exception {
        Class.forName("com.mysql.jdbc.Driver");
        Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/test", "root", "root");
        return new MySqlConnection(conn, "test");
    }
    //获取输入数据流
    @Override
    protected IDataSet getDataSet() throws Exception {
        InputStream is = getClass().getResourceAsStream("/test-data.xml");
        return new FlatXmlDataSetBuilder().build(is);
    }
    //测试数据的创建
    public void testCreate() throws Exception{
        User user = new User();
        user.setName("testdata");
        user.setPassword("testPassword");
        user.setUsername("testAdmin");
        Long id = userService.create(user);
        assertNotNull(id);
        User dbUser =userService.get(id);
        assertNotNull(dbUser);
        assertEquals("testAdmin", dbUser.getUsername());
        assertEquals("testPassword", dbUser.getPassword());
        assertEquals("testAdministrator", dbUser.getName());
    }
    public void testGet() throws Exception{
        User user = userService.get(1L);
        assertNotNull(user);
        assertEquals("admin1", user.getUsername());
        assertEquals("", user.getPassword());
        assertEquals("Administrator1", user.getName());
        User nullUser = userService.get(0L);
        assertNull(nullUser);
    }
    public void testDelete() throws Exception{
        User user = userService.get(1L);
        assertNotNull(user);
        userService.delete(1L);
        User nullUser = userService.get(1L);
        assertNull(nullUser);
    }
    public void testList() throws Exception{
        List<User> users = userService.list();
        assertNotNull(users);
        assertEquals(, users.size());
    }
}
UserServiceTestCase.java文件
public class UserServiceTestCase extends TestCase{
    private UserService userService;
    private File backupFile=new File("resource/backup-data.xml");
    @Override
    protected void setUp() throws Exception {
        userService=new UserServiceImpl();
    }
    @Before
    public void setUpData() throws Exception {
        //备份原来的数据
        DBUnitUtils.backupDatabase(new String []{"user"}, backupFile);
        //导入测试数据
        DBUnitUtils.importTables(new File("resource/test-data.xml"));
    }
    @After
    public void tearDownData() throws Exception{
        //恢复备份数据
        DBUnitUtils.resumeDatabase(backupFile);
        //关闭数据库连接
        DButils.closeConnection();
    }
    public void testCreate() throws Exception{
        DBUnitUtils.importTables(new File("resource/test-data.xml"));
        User user = new User();
        DBUnitUtils.resumeDatabase(backupFile);
        DButils.closeConnection();
        user.setName("testdata");
        user.setPassword("testPassword");
        user.setUsername("testAdmin");
        Long id = userService.create(user);
        assertNotNull(id);
        User dbUser =userService.get(id);
        assertNotNull(dbUser);
        assertEquals("testAdmin", dbUser.getUsername());
        assertEquals("testPassword", dbUser.getPassword());
        assertEquals("testAdministrator", dbUser.getName());
    }
    public void testGet() throws Exception{
        User user = userService.get(1L);
        assertNotNull(user);
        assertEquals("admin1", user.getUsername());
        assertEquals("", user.getPassword());
        assertEquals("Administrator1", user.getName());
        User nullUser = userService.get(0L);
        assertNull(nullUser);
    }
    public void testDelete() throws Exception{
        User user = userService.get(1L);
        assertNotNull(user);
        userService.delete(1L);
        User nullUser = userService.get(1L);
        assertNull(nullUser);
    }
    public void testList() throws Exception{
        List<User> users = userService.list();
        assertNotNull(users);
        assertEquals(, users.size());
    }
}
test-data.xml文件
<?xml version='1.0' encoding='UTF-8'?>
<dataset>
<user id="" username="test-user1" password="test-user1" name="test-user1"/>
<user id="" username="test-user2" password="test-user2" name="test-user2"/>
</dataset>
接下来测试结果: 

demo代码下载: dbunitDemo
总结: 
      使用了DBUnit后可以实现了对数据库的隔离,成功弥补了JUnit单元测试不清理数据现场的缺憾,实际上DBUnit只是简单的在单元测试前把数据库的数据进行了备份然后插入xml中配置好的数据,在测试结束后再用备份好的原数据库数据填充回数据库.但当面对复杂的表关系和大数据量的时候,每次进行测试都进行数据的备份,也是一个很大的负担,而且把全部的测试数据都编写在xml当中也是很大的工作量
DBUnit使用介绍的更多相关文章
- 玩转单元测试之DBUnit
		DBunit 是一种扩展于JUnit的数据库驱动测试框架,它使数据库在测试过程之间处于一种已知状态,如果一个测试用例对数据库造成了破坏性影响,它可以帮助避免造成后面的测试失败或者给出错误结果. 虽然不 ... 
- java开发常用jar包介绍(转载)
		jta.jar 标准JTA API必要 commons-collections.jar 集合类 必要 antlr.jar ANother Tool for Language Recognition ... 
- JAR包介绍大全用途作用详解JAVA
		jta.jar 标准JTA API必要commons-collections.jar 集合类 必要antlr.jar ANother Tool for Language Recognition 必要 ... 
- spring boot应用测试框架介绍
		一.spring boot应用测试存在的问题 官方提供的测试框架spring-boot-test-starter,虽然提供了很多功能(junit.spring test.assertj.hamcres ... 
- 玩转单元測试之DBUnit
		本文同一时候发表在:http://www.cnblogs.com/wade-xu/p/4547381.html DBunit 是一种扩展于JUnit的数据库驱动測试框架,它使数据库在測试过程之间处于一 ... 
- 05.DBUnit的使用
		相信做过单元测试的人都会对JUnit 非常的熟悉了,今天要介绍的DbUnit(http://dbunit.sourceforge.net/ ) 则是专门针对数据库测试的对JUnit 的一个扩展,它可以 ... 
- DbUnit入门实战
		原文地址: http://yangzb.iteye.com/blog/947292 相信做过单元测试的人都会对JUnit 非常的熟悉了, 今天要介绍的DbUnit(http://dbunit.sour ... 
- CSS3 background-image背景图片相关介绍
		这里将会介绍如何通过background-image设置背景图片,以及背景图片的平铺.拉伸.偏移.设置大小等操作. 1. 背景图片样式分类 CSS中设置元素背景图片及其背景图片样式的属性主要以下几个: ... 
- MySQL高级知识- MySQL的架构介绍
		[TOC] 1.MySQL 简介 概述 MySQL是一个关系型数据库管理系统,由瑞典MySQL AB公司开发,目前属于Oracle公司. MySQL是一种关联数据库管理系统,将数据保存在不同的表中,而 ... 
随机推荐
- Union、Union All、Intersect、Minus用法和区别
			假设我们有一个表Student,包括以下字段与数据: [c-sharp] view plain copydrop table student; create table student ( ... 
- WPF usercontrol 自定义依赖属性
			1.依赖属性不同意一般属性,一般属性主要定义在对象中,而依赖属性是存在一个特殊的依赖属性表中.2.当我们触发改变值时,需要通过SetValue这种方式进行触发. UserControl1.xaml: ... 
- mongodb的存储引擎
			mongodb版本为3.4 mongodb存储引起的一些概述 存储引擎是MongoDB的核心组件,负责管理数据如何存储在硬盘和内存上.从MongoDB 3.2 版本开始,MongoDB 支持多数据存储 ... 
- 20145312《网络对抗》 逆向及Bof基础实践
			20145312 <网络对抗> 逆向及Bof基础实践 1 逆向及Bof基础实践说明 1.1 实践目标 本次实践的对象是一个名为pwn1的linux可执行文件. 该程序正常执行流程是:mai ... 
- 20145204 《Java程序设计》第7周学习总结
			20145204 <Java程序设计>第7周学习总结 教材学习内容总结 时间 GMT.UT.TAI 格林威治标准时间(GMT)的正午是太阳抵达天空最高点之时,因为地球公转轨道为椭圆且速度不 ... 
- 搭建linux上的Eclipse+PHP编程环境
			最近打算学PHP,于是查阅资料搭建了ubuntu(14.04.3)上的PHP IDE环境 一.准备工作(可略) 主要是推荐科大的源和配置源的方法,因为后于步骤使用到了apt,科大的源非常快,并且有个针 ... 
- 开源工具-Json 解析器 Jackson 的使用
			Json已经成为当前服务器与 WEB 应用之间数据传输的公认标准.Java 中常见的 Json 类库有 Gson.JSON-lib 和 Jackson 等.相比于其他的解析工具,Jackson 简单易 ... 
- 【联网】虚拟机下Linux(终端)配置网络的方法
			这几天在虚拟机vmware上部署centos系统,想通过内部联网用yum命令安装必需的软件,但是一直不能静态地址联网,今天终于找到一个方法centos内部设置IP,对外联网.设置过程如下: 1.首先是 ... 
- C++ 自定义错误类
			#include <iostream> #include <exception> using namespace std; struct MyException : publi ... 
- POJ 1170 Shopping Offers(完全背包+哈希)
			http://poj.org/problem?id=1170 题意:有n种花的数量和价格,以及m种套餐买法(套餐会便宜些),问最少要花多少钱. 思路:题目是完全背包,但这道题目不好处理的是套餐的状态, ... 
