相信做过单元测试的人都会对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(); } } }