DbUnit入门教程,,DBUnit是JUnit
DbUnit入门教程,,DBUnit是JUnit
DBUnit是JUnit的一个扩展,对于数据库驱动的项目而言(基本上所有的Web项目都是数据库驱动的),对于服务层的单元测试非常麻烦,因为不能保证每次测试时数据库都是同一个状态,所以开发者不敢写断言(assertEquals())。我个人也是因为这个原因所以对驱动测试开发总是敬而远之。
有了DBUnit,一切都变了,DBUnit的目的就是在每个单元测试运行之前将数据库初始化成一个预定义的状态,以保证单元测试时的断言不会因为数据库状态发生了变化而失败,同时可以解决前一个单元测试失败导致对数据库的操作未按照测试用例执行而影响后一个单元测试的问题。
DBUnit可以将数据库中的数据导出成XML数据集,也可以将XML数据集重新导入到数据库中,这也是DBUnit实现测试前初始化数据库状态的实现方法,而且,DBUnit还可以验证数据库中的模式和数据是不是和XML数据集中的模式和数据是否一样,也就是真正意义上的“数据库测试”,不过DBUnit貌似还不支持数据库存储过程、触发器、视图等高级功能的测试。DBUnit2.0增强了对于流模式下巨型XML数据集的支持。相信信仰单元测试驱动开发或者有意向在开发中加入单元测试的开发者很容易理解上面的叙述,下面用一个示例演示DBUnit的功能。
假设我们开发中已经建立了一个数据库,里面只有一个数据表user:
CREATE TABLE USER(id BIGINT auto_increament PRIMARY KEY,username CHAR(48) NOT NULL,password CHAR(48) NOT NULL,name VARCHAR(48) NOT NULL);
其中有一行数据:
INSERT INTO USER(id, username, password, name) VALUES(1, 'admin', '123', 'Administrator');
第一步是根据测试数据建立XML数据集,DBUnit用下面的格式来表示一行数据:
<user id="1" username="admin" password="123" name="Administrator"/>
一个XML数据集应该具有如下格式:
<?xml version="1.0" encoding="UTF-8"?><dataset> <user id="1" username="admin1" password="123" name="Administrator1" /> <user id="2" username="admin2" password="123" name="Administrator2" /> <user id="3" username="admin3" password="123" name="Administrator3" /></dataset>
一般,最好对每个需要数据库驱动的测试用例都建立一个XML数据集,一方面可以保证单元测试之间完全的数据独立,另一方面可以只设置测试需要的数据,尽量使XML数据集保持简单可控。
第二步就可以开始编码了,DBUnit提供了一个抽象类DatabaseTestCase,这个类继承了JUnit的TestCase类,其中定义了两个抽象方法:
/** * 返回测试用的数据库连接对象 */protected abstract IDatabaseConnection getConnection() throws Exception;/** * 返回测试用XML数据集对象 */protected abstract IDataSet getDataSet() throws Exception; getConnection()的返回值类型为IDatabaseConnection,对java.sql.Connection进行了简单的封装,可以简单的实现如下:protected IDatabaseConnection getConnection() throws Exception { Class.forName("com.mysql.jdbc.Driver"); Connection conn = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/dbunitdemo", "root", "admin"); return new MySqlConnection(conn, "dbunitdemo");//本人用的是MySQL}
getDataSet()
的返回值是IDataSet类型,即从XML数据集中读取数据和结构,实例化为IDataSet对象,可以简单实现如下:
protected IDataSet getDataSet() throws Exception { InputStream is = new FileInputStream("dbunitdemo-seed.xml"); return new FlatXmlDataSet(is);}
定义了以上两个方法后,DBUnit就可以工作了,但是不少人会就会想到一个问题,如果数据库中存在以前的数据,而我需要将这些数据删除,DBUnit会自动的帮我做这些事情么?事实上,很显然DBUnit会,其默认操作就是删除数据,同时将XML数据集中的数据插入到数据库中,不过DBUnit也允许我们通过覆盖DatabaseTestCase中的getSetUpOperation()方法来实现自己的动作,在DatabaseTestCase中默认实现是这样的:
protected DatabaseOperation getSetUpOperation() throws Exception{ return DatabaseOperation.CLEAN_INSERT;}
DatabaseOperation
是DBUnit定义的数据库操作对象,CLEAN_INSERT代表清空数据、插入XML数据集数据的操作。
与SetUpOperation对象就有TearDownOperation,表示结束测试的时候做的事情,DatabaseTestCase的默认实现是什么都不做:
protected DatabaseOperation getTearDownOperation() throws Exception{ return DatabaseOperation.NONE;}
同样,开发者可以根据自己的需求来改变默认操作。
基本原理就已经讲解完了,我写了一个例子程序,实现了一个领域模型类(User),一个Dao接口(IUserDao),定义了list\save\get\delete四个基本方法,一个用JDBC实现的Dao接口实现类(UserDaoImpl),建立一个UserDaoTest对JBDC版本的Dao实现类进行测试。
例子程序下载地址:dbunitdemo_jdbc_1.0.zip
另外这个工程使用maven进行build,如果你对maven还是不很了解,请查考《Maven权威指南》
下载工程后,在项目根目录下执行mvn sql:execute,将使用Maven Sql插件导入src/main/sql/dbunitdemo.sql中的数据库脚本到数据库中。
然后可以直接运行mvn test进行单元测试,测试报告会在命令行输出,同时在target\surefire-reports下也会生成DBUnit报告
本文转载自:周亮的博客
用户点评