相信做过单元测试的人都会对JUnit 非常的熟悉了,今天要介绍的DbUnit(http://dbunit.sourceforge.net/ ) 则是专门针对数据库测试的对JUnit 的一个扩展,它可以将测试对象数据库置于一个测试轮回之间的状态。鉴于目前国内介绍DbUnit 的系统教程比较少见,本文将分从理论和实例两个方面带你领略DbUnit 的精彩世界。

上面一节中我们使用了hashmap来模拟操作真正的数据库,这一章中我们可以使用dbunit工具来测试数据库的操作

第一步我们首先下载对应的jar包

需要上面的两个jar包

第二步在src目录下创建xml文件,xml文件的名字要和测试的数据库中的表名一样 t_user.xml

<?xml version="1.0" encoding="UTF-8"?>
<dataset>
<t_user id ="1" username="admin" password="123" nickname="超级管理员"/> </dataset>

也可以采用下面的方式创建

二者却别在于使用的DataSet不一样,xml方式使用的是XmlDataSet,上面第一种方式使用的是FlatXmlDataSet

第三步:创建dbunit的conncetion

依赖上面章节中DButils中创建的connection

DatabaseOperation.UPDATE:这个操作将从测试数据源中读取的数据集的内容更新到数据库中,注意这个操作正确执行的前提是测试数据表已经存在,如果不存在这个测试用例将会失败

DatabaseOperation.INSERT:这个操作把从测试数据源中读取的数据集的内容插入到数据库中,注意这个操作正确执行的前提是测试数据表不存在,这个操作将新建数据表。如果测试数据表已经存在这个测试用例将会失败。另外,在执行这个操作的时候要特别注意数据集中数据表的顺序,否则可能会因为违反外键约束而造成测试用例失败

DatabaseOperation.DELETE:这个操作会从数据库中删除数据,注意,这个操作只删除数据集中存在的数据行而不是整个数据表中的数据

DatabaseOperation.DELETE_ALL:这个操作删除数据表中的所有行,注意,这个操作也只影响数据集中声明了的数据表,数据集中没有涉及到的数据表中的数据不会删除

DatabaseOperation.TRUNCATE:这个操作将删除数据集中声明的数据表,如果数据中有些表并没有在预定义的数据集中提到,这个数据表将不会被影响。注意,这个操作是按照相反的顺序执行的

DatabaseOperation.REFRESH:顾名思义,这个操作将把预定义数据集中的数据同步到数据库中,也就是说这个操作将更新数据数中已有的数据、插入数据库中没有的数据。数据库中已有的、但是数据集中没有的行将不会被影响。我们用一个产品数据库的拷贝进行测试的时候可以使用这个操作将预定义数据同步到产品数据库中

DatabaseOperation.CLEAN_INSERT:删除所有的数据表中的数据,然后插入数据集中定义的数据,如果你想保证数据库是受控的,这个你会比较喜欢。

DatabaseOperation.NONE:不执行任何操作

CompositeOperation:将多个操作组合成一个,便以维护和重用

TransactionOperation:在一个事物内执行多个操作

IdentityInsertOperation:在使用MSSQL的时候,插入数据时IDENTITY列我们是没有办法控制的,用这个就可以控制了,只有在使用MSSQL的时候才会用得到

我们编写我们的测试类

package com.fjnu.service;

import java.sql.SQLException;
import static org.junit.Assert.*; import org.dbunit.DatabaseUnitException;
import org.dbunit.database.DatabaseConnection;
import org.dbunit.database.IDatabaseConnection;
import org.dbunit.dataset.IDataSet;
import org.dbunit.dataset.xml.FlatXmlDataSet;
import org.dbunit.dataset.xml.FlatXmlProducer;
import org.dbunit.operation.DatabaseOperation;
import org.junit.Test;
import org.xml.sax.InputSource; import com.fjnu.model.User;
import com.weiyuan.dao.IUserDao;
import com.weiyuan.dao.UserDao;
import com.weiyuan.test.DBUtils; public class TestDBUtils {
@Test
public void testLoad(){
try {
IDatabaseConnection con = new DatabaseConnection(DBUtils.getConnection());
IDataSet dataSet = new FlatXmlDataSet(new FlatXmlProducer(
new InputSource(TestDBUtils.class.getClassLoader().getResourceAsStream("t_user.xml"))));
//清空数据库中的数据并插入xml中的数据
DatabaseOperation.CLEAN_INSERT.execute(con,dataSet); IUserDao userDao = new UserDao();
User u = userDao.load("admin");
assertEquals(u.getUsername(), "admin55");
assertEquals(u.getPassword(), "123"); } catch (DatabaseUnitException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} }

这样就可以了

上面这种方式存在问题,它首先是清空数据库中的所有数据,再将xml中的文件插入到数据库中

在实际的操作中:我们应该先备份数据库中的所有数据,然后再操作xml中的数据,然后操作完成之后还原备份的数据

package com.fjnu.service;

import java.io.FileWriter;
import java.sql.SQLException; import static org.junit.Assert.*; import org.dbunit.DatabaseUnitException;
import org.dbunit.database.DatabaseConnection;
import org.dbunit.database.IDatabaseConnection;
import org.dbunit.dataset.IDataSet;
import org.dbunit.dataset.xml.FlatXmlDataSet;
import org.dbunit.dataset.xml.FlatXmlProducer;
import org.dbunit.operation.DatabaseOperation;
import org.junit.Test;
import org.xml.sax.InputSource; import com.fjnu.model.User;
import com.weiyuan.dao.IUserDao;
import com.weiyuan.dao.UserDao;
import com.weiyuan.test.DBUtils; public class TestDBUtils {
@Test
public void testLoad(){
try {
IDatabaseConnection con = new DatabaseConnection(DBUtils.getConnection());
IDataSet dataSet = new FlatXmlDataSet(new FlatXmlProducer(
new InputSource(TestDBUtils.class.getClassLoader().getResourceAsStream("t_user.xml"))));
//清空数据库中的数据并插入xml中的数据
DatabaseOperation.CLEAN_INSERT.execute(con,dataSet); IUserDao userDao = new UserDao();
User u = userDao.load("admin");
assertEquals(u.getUsername(), "admin");
assertEquals(u.getPassword(), "123"); } catch (DatabaseUnitException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} @Test
public void testBackup(){
try {
IDatabaseConnection con = new DatabaseConnection(DBUtils.getConnection());
IDataSet createDataSet = con.createDataSet();
FlatXmlDataSet.write(createDataSet, new FileWriter("d:/test.xml"));
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
} } }

IDataSet createDataSet = con.createDataSet();是备份数据库中所有的表

如果我们只备份某张表

可以使用queryDataSet来设置表

package com.fjnu.service;

import java.io.FileWriter;
import java.sql.SQLException; import static org.junit.Assert.*; import org.dbunit.DatabaseUnitException;
import org.dbunit.database.DatabaseConnection;
import org.dbunit.database.IDatabaseConnection;
import org.dbunit.dataset.IDataSet;
import org.dbunit.dataset.xml.FlatXmlDataSet;
import org.dbunit.dataset.xml.FlatXmlProducer;
import org.dbunit.operation.DatabaseOperation;
import org.junit.Test;
import org.xml.sax.InputSource; import com.fjnu.model.User;
import com.weiyuan.dao.IUserDao;
import com.weiyuan.dao.UserDao;
import com.weiyuan.test.DBUtils; public class TestDBUtils {
@Test
public void testLoad(){
try {
IDatabaseConnection con = new DatabaseConnection(DBUtils.getConnection());
IDataSet dataSet = new FlatXmlDataSet(new FlatXmlProducer(
new InputSource(TestDBUtils.class.getClassLoader().getResourceAsStream("t_user.xml"))));
//清空数据库中的数据并插入xml中的数据
DatabaseOperation.CLEAN_INSERT.execute(con,dataSet); IUserDao userDao = new UserDao();
User u = userDao.load("admin");
assertEquals(u.getUsername(), "admin");
assertEquals(u.getPassword(), "123"); } catch (DatabaseUnitException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} //备份数据库文件
@Test
public void testBackup(){
try {
IDatabaseConnection con = new DatabaseConnection(DBUtils.getConnection());
IDataSet createDataSet = con.createDataSet();
FlatXmlDataSet.write(createDataSet, new FileWriter("d:/test.xml"));
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
} } //还原数据库文件
@Test
public void testResume(){
try {
IDatabaseConnection con = new DatabaseConnection(DBUtils.getConnection());
IDataSet dataSet = new FlatXmlDataSet(new FlatXmlProducer(
new InputSource("d:/test.xml")));
//清空数据库中的数据并插入xml中的数据
DatabaseOperation.CLEAN_INSERT.execute(con,dataSet);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
} } }

05.DBUnit的使用的更多相关文章

  1. Java学习笔记(05)

    目录: static的用法 主函数的定义 增强for的循环 单例设计模式 封装 一.Static的用法 1.对象的内存分析 对象的引用变量是存在于栈区,而在堆区开辟了一块内存空间,调用对象给成员变量赋 ...

  2. iOS系列 基础篇 05 视图鼻祖 - UIView

    iOS系列 基础篇 05 视图鼻祖 - UIView 目录: UIView“家族” 应用界面的构建层次 视图分类 最后 在Cocoa和Cocoa Touch框架中,“根”类时NSObject类.同样, ...

  3. 【web开发 | 移动APP开发】 Web 移动开发指南(2017.01.05更新)

    版本记录 - 版本1.0 创建文章(2016.12.30) - 版本1.1 更正了hybird相关知识:增加了参考文章(2017.01.05): + Web APP更正为响应式移动站点与页面,简称响应 ...

  4. javaSE基础05

    javaSE基础05:面向对象 一.数组 数组的内存管理 : 一块连续的空间来存储元素. Int [ ] arr = new int[ ]; 创建一个int类型的数组,arr只是一个变量,只是数组的一 ...

  5. 异步编程系列第05章 Await究竟做了什么?

    p { display: block; margin: 3px 0 0 0; } --> 写在前面 在学异步,有位园友推荐了<async in C#5.0>,没找到中文版,恰巧也想提 ...

  6. javascript基础05

    javascript基础05 1.变量的作用域 变量既可以是全局,也可以是局部的. 全局变量:可以在脚本中的任何位置被引用,一旦你在某个脚本里声明了全局变量,你就可以 在这个脚本的任何位置(包括函数内 ...

  7. Linux 第05天

    Linux 第05天 1.连接到Internet 1.1 配置网络信息 dmesg命令————查看网卡信息 dmesg | grep -i net ifconfig命令————查看IP.网关等相关信息 ...

  8. org.dbunit.database.ambiguoustablenameexception

    对于一个数据库下面多个shema的情况,如果使用DBUNIT配置会出现,上面的错误,不清楚的表名,解决如下 增加红色的shema指定 参考:http://stackoverflow.com/quest ...

  9. 转:使用DBUnit测试时违反外键约束的解决办法

    DBUnit是一个基于junit扩展的数据库测试框架.它提供了大量的类对与数据库相关的操作进行了抽象和封装.它会把数据库表里的数据和一个xml文件关联起来,也就是说它可以让数据在XML文件和数据库之间 ...

随机推荐

  1. JSP指令 & 中文乱码问题

    1. JSP 指令: JSP指令(directive)是为JSP引擎而设计的,     它们并不直接产生任何可见输出, 而只是告诉引擎如何处理JSP页面中的其余部分. 2. 在JSP 2.0中,定义了 ...

  2. SSIS 数据类型 第二篇:变量的数据类型

    变量(Variable)用于存储在Package运行时用到的值,集成服务支持两种类型的变量:用户自定义的变量和系统变量,自定义的变量由用户来定义,系统变量由集成服务来定义. 变量的用途十分广泛,用于容 ...

  3. 【补充说明】Gauge框架在JS中的简单应用

    这里做一个总结 由于公司架构要用node来替代Java的部分服务,所以就研究了这个自动化测试框架:它可以很方便的测试我们的接口,而且还能使用断言[assert]来判断是否是我们预期的结果. 但是呢,由 ...

  4. Rocket - debug - TLDebugModuleInner - Program Buffer

    https://mp.weixin.qq.com/s/kjhJJ3moRQzxHt6pJOXEgg 简单介绍TLDebugModuleInner中Program Buffer寄存器的实现. 1. pr ...

  5. js函数prototype属性学习(二)

    继续探讨js对象的prototype属性,前面已经看到在创建完一个对象之后,随时都会有一个_proto_属性伴随所有,那么,这个_proto_又是用来干嘛的,面试时问的高大上的原型链又是怎么回事? 拿 ...

  6. JavaScript (一) js的介绍及基本语法变量

    个人博客网:https://wushaopei.github.io/    (你想要这里多有) 一.JS 的 介绍 1.JavaScript :简称 : js js 分为三个部分: 1. ECMASc ...

  7. 使用turtle库绘制一个六角形

    from turtle import * color("black","red") begin_fill() pu() fd(-200) pd() seth(3 ...

  8. Java实现 蓝桥杯 算法提高 和谐宿舍2

    试题 算法提高 和谐宿舍2 资源限制 时间限制:1.0s 内存限制:256.0MB 问题描述 我的某室友学过素描,墙上有n张他的作品.这些作品都是宽度为1,高度不定的矩形,从左到右排成一排,且底边在同 ...

  9. java实现漏掉的账目明细

    某财务部门结账时发现总金额不对头.很可能是从明细上漏掉了某1笔或几笔.如果已知明细账目清单,能通过编程找到漏掉的是哪1笔或几笔吗? 如果有多种可能,则输出所有可能的情况. 我们规定:用户输入的第一行是 ...

  10. 基于EntityFramework 6 Code First实现动态建库,分库,数据库自动迁移

    一.前言 公司原本有一个"xx系统",ORM使用EntityFramework,Code First模式.该系统是针对某个客户企业的,现要求该系统支持多个企业使用,但是又不能给每个 ...