一、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使用介绍的更多相关文章

  1. 玩转单元测试之DBUnit

    DBunit 是一种扩展于JUnit的数据库驱动测试框架,它使数据库在测试过程之间处于一种已知状态,如果一个测试用例对数据库造成了破坏性影响,它可以帮助避免造成后面的测试失败或者给出错误结果. 虽然不 ...

  2. java开发常用jar包介绍(转载)

    jta.jar 标准JTA API必要 commons-collections.jar 集合类 必要 antlr.jar  ANother Tool for Language Recognition ...

  3. JAR包介绍大全用途作用详解JAVA

    jta.jar 标准JTA API必要commons-collections.jar 集合类 必要antlr.jar  ANother Tool for Language Recognition 必要 ...

  4. spring boot应用测试框架介绍

    一.spring boot应用测试存在的问题 官方提供的测试框架spring-boot-test-starter,虽然提供了很多功能(junit.spring test.assertj.hamcres ...

  5. 玩转单元測试之DBUnit

    本文同一时候发表在:http://www.cnblogs.com/wade-xu/p/4547381.html DBunit 是一种扩展于JUnit的数据库驱动測试框架,它使数据库在測试过程之间处于一 ...

  6. 05.DBUnit的使用

    相信做过单元测试的人都会对JUnit 非常的熟悉了,今天要介绍的DbUnit(http://dbunit.sourceforge.net/ ) 则是专门针对数据库测试的对JUnit 的一个扩展,它可以 ...

  7. DbUnit入门实战

    原文地址: http://yangzb.iteye.com/blog/947292 相信做过单元测试的人都会对JUnit 非常的熟悉了, 今天要介绍的DbUnit(http://dbunit.sour ...

  8. CSS3 background-image背景图片相关介绍

    这里将会介绍如何通过background-image设置背景图片,以及背景图片的平铺.拉伸.偏移.设置大小等操作. 1. 背景图片样式分类 CSS中设置元素背景图片及其背景图片样式的属性主要以下几个: ...

  9. MySQL高级知识- MySQL的架构介绍

    [TOC] 1.MySQL 简介 概述 MySQL是一个关系型数据库管理系统,由瑞典MySQL AB公司开发,目前属于Oracle公司. MySQL是一种关联数据库管理系统,将数据保存在不同的表中,而 ...

随机推荐

  1. 20145105 《Java程序设计》实验一总结

    实验一   Java开发环境的熟悉 一.    实验内容: (一)使用JDK编译.运行简单的程序 (二)使用idea编辑.编译.运行.调试Java程序. 二.    实验步骤: (一)   命令行下J ...

  2. 20145315 《Java程序设计》第七周学习总结

    20145315 <Java程序设计>第七周学习总结 教材学习内容总结 第十三章 时间与日期 13.1.1时间的度量 1.格林威治时间(GMT):参考太阳到达最高点,有时间误差. 2.世界 ...

  3. Windows10系统远程桌面连接出现卡顿如何解决

    最新的windows10系统下,用户只要开启远程桌面连接,就能够轻松地操控其他电脑.但是,最近部分用户在win10中启用远程连接时,发现电脑窗口变得非常缓慢卡顿,这是怎么回事呢?其实,该问题与系统的设 ...

  4. ImportError: libcublas.so.9.0: cannot open shared object file: No such file or directory 【学习笔记】【原创】

    作者:庄泽彬(欢迎转载,请注明作者) 说明:千辛万苦终于在ubuntu18.04上安装好cuda9.1与cudnn7.0.5,但是导入import tensorflow as tf却报了这个错误. 上 ...

  5. 菜单项onCreateOptionsMenu()和onOptionsItemSelected()的使用

    Java源文件 package com.example.macname.myapplication; import android.support.v7.app.AppCompatActivity; ...

  6. KMP与AC自动机

    KMP算法主要思想就是预处理出失配函数, 从而减少匹配失败时的回溯, 复杂度是$\Theta(m+n)$, 已达到理论下界 c++代码如下 int n, f[N]; char t[N], p[N]; ...

  7. 一张思维导图教你使用google一下

    导图总览 google搜索技巧.png 双引号 代表完全匹配搜索 也就是说搜索结果返回的页面包含双引号中出现的所有的词,连顺序也必须完全匹配 例如搜索"java 排序"与无引号的j ...

  8. Oracle Sourcing Implementation and Administration Guide(转)

    原文地址 Oracle Sourcing Implementation and Administration Guide

  9. IOS-网络(文件压缩和解压缩)

    // // ViewController.m // IOS_0206_文件上传 // // Created by ma c on 16/2/6. // Copyright © 2016年 博文科技. ...

  10. [转载]Morris Traversal方法遍历二叉树(非递归,不用栈,O(1)空间)

    本文主要解决一个问题,如何实现二叉树的前中后序遍历,有两个要求: 1. O(1)空间复杂度,即只能使用常数空间: 2. 二叉树的形状不能被破坏(中间过程允许改变其形状). 通常,实现二叉树的前序(pr ...