﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-liuzheng-文章分类-DBUnit</title><link>http://www.blogjava.net/liuzheng/category/30542.html</link><description /><language>zh-cn</language><lastBuildDate>Thu, 24 Apr 2008 19:11:18 GMT</lastBuildDate><pubDate>Thu, 24 Apr 2008 19:11:18 GMT</pubDate><ttl>60</ttl><item><title>dbunit test 的一个小缺陷</title><link>http://www.blogjava.net/liuzheng/articles/195613.html</link><dc:creator>刘铮 </dc:creator><author>刘铮 </author><pubDate>Thu, 24 Apr 2008 08:00:00 GMT</pubDate><guid>http://www.blogjava.net/liuzheng/articles/195613.html</guid><wfw:comment>http://www.blogjava.net/liuzheng/comments/195613.html</wfw:comment><comments>http://www.blogjava.net/liuzheng/articles/195613.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/liuzheng/comments/commentRss/195613.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/liuzheng/services/trackbacks/195613.html</trackback:ping><description><![CDATA[row 的顺序要有讲究，最新的数据行应该在前面<br />
比如albert2@eln.dev&nbsp;，2是新加的，那么应该在前面，不然要报错<br />
&lt;table name="accountaddress"&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;column&gt;address&lt;/column&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;column&gt;accountid&lt;/column&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;row&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;value&gt;albert2@eln.dev&lt;/value&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;value&gt;2&lt;/value&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/row&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;row&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;value&gt;albert@eln.dev&lt;/value&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;value&gt;2&lt;/value&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/row&gt;<br />
&nbsp;&lt;/table&gt;
<img src ="http://www.blogjava.net/liuzheng/aggbug/195613.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/liuzheng/" target="_blank">刘铮 </a> 2008-04-24 16:00 <a href="http://www.blogjava.net/liuzheng/articles/195613.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>dbunit test 的一个小缺陷</title><link>http://www.blogjava.net/liuzheng/articles/195615.html</link><dc:creator>刘铮 </dc:creator><author>刘铮 </author><pubDate>Thu, 24 Apr 2008 08:00:00 GMT</pubDate><guid>http://www.blogjava.net/liuzheng/articles/195615.html</guid><wfw:comment>http://www.blogjava.net/liuzheng/comments/195615.html</wfw:comment><comments>http://www.blogjava.net/liuzheng/articles/195615.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/liuzheng/comments/commentRss/195615.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/liuzheng/services/trackbacks/195615.html</trackback:ping><description><![CDATA[row 的顺序要有讲究，最新的数据行应该在前面<br />
比如albert2@eln.dev&nbsp;，2是新加的，那么应该在前面，不然要报错<br />
&lt;table name="accountaddress"&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;column&gt;address&lt;/column&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;column&gt;accountid&lt;/column&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;row&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;value&gt;albert2@eln.dev&lt;/value&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;value&gt;2&lt;/value&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/row&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;row&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;value&gt;albert@eln.dev&lt;/value&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;value&gt;2&lt;/value&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/row&gt;<br />
&nbsp;&lt;/table&gt;
<img src ="http://www.blogjava.net/liuzheng/aggbug/195615.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/liuzheng/" target="_blank">刘铮 </a> 2008-04-24 16:00 <a href="http://www.blogjava.net/liuzheng/articles/195615.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>DbUnit入门实战(转)</title><link>http://www.blogjava.net/liuzheng/articles/190128.html</link><dc:creator>刘铮 </dc:creator><author>刘铮 </author><pubDate>Tue, 01 Apr 2008 08:30:00 GMT</pubDate><guid>http://www.blogjava.net/liuzheng/articles/190128.html</guid><wfw:comment>http://www.blogjava.net/liuzheng/comments/190128.html</wfw:comment><comments>http://www.blogjava.net/liuzheng/articles/190128.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/liuzheng/comments/commentRss/190128.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/liuzheng/services/trackbacks/190128.html</trackback:ping><description><![CDATA[<strong>DbUnit入门实战<br />
<br />
</strong><br />
相信做过单元测试的人都会对JUnit非常的熟悉了，今天要介绍的DbUnit(http://dbunit.sourceforge.net/)则是专门针对数据库测试的对JUnit的一个扩展，它可以将测试对象数据库置于一个测试轮回之间的状态。鉴于目前国内介绍DbUnit的系统教程比较少见，本文将分从理论和实例两个方面带你领略DbUnit的精彩世界。<br />
<br />
DbUnit设计理念<br />
熟悉单元测试的开发人员都知道，在对数据库进行单元测试时候，通常采用的方案有运用模拟对象(mock objects)和stubs两种。通过隔离关联的数据库访问类，比如JDBC的相关操作类，来达到对数据库操作的模拟测试。然而某些特殊的系统，比如利用了EJB的CMP(container-managed persistence)的系统，数据库的访问对象是在最底层而且很隐蔽的，那么这两种解决方案对这些系统就显得力不从心了。<br />
<br />
DBUnit的设计理念就是在测试之前，备份数据库，然后给对象数据库植入我们需要的准备数据，最后，在测试完毕后，读入备份数据库，回溯到测试前的状态；<br />
而且又因为DBUnit是对JUnit的一种扩展，开发人员可以通过创建测试用例代码，在这些测试用例的生命周期内来对数据库的操作结果进行比较。<br />
<br />
DbUnit测试基本概念和流程<br />
基于DbUnit 的测试的主要接口是IDataSet。IDataSet代表一个或多个表的数据。<br />
可以将数据库模式的全部内容表示为单个IDataSet 实例。这些表本身由Itable 实例来表示。<br />
IDataSet 的实现有很多，每一个都对应一个不同的数据源或加载机制。最常用的几种 IDataSet实现为： <br />
FlatXmlDataSet：数据的简单平面文件 XML 表示 <br />
QueryDataSet：用 SQL 查询获得的数据 <br />
DatabaseDataSet：数据库表本身内容的一种表示 <br />
XlsDataSet ：数据的excel表示<br />
<br />
一般而言，使用DbUnit进行单元测试的流程如下：<br />
1 根据业务，做好测试用的准备数据和预想结果数据，通常准备成xml格式文件。<br />
2 在setUp()方法里边备份数据库中的关联表。<br />
3 在setUp()方法里边读入准备数据。<br />
4 对测试类的对应测试方法进行实装:执行对象方法，把数据库的实际执行结果和预想结果进行比较。<br />
5 在tearDown()方法里边,把数据库还原到测试前状态。<br />
<p>DbUnit开发实例<br />
下面通过一个实例来说明DbUnit的实际运用。<br />
<br />
实例准备<br />
比如有一个学生表[student]，结构如下：<br />
<hr />
id char(4) pk 学号<br />
name char(50) 姓名<br />
sex char(1) 性别<br />
birthday date 出生日期<br />
<hr />
准备数据如下：<br />
<hr />
id name sex birthday<br />
0001 翁仔 m 1979-12-31<br />
0002 王翠花 f 1982-08-09
<hr />
测试对象类为StudentOpe.java，里边有2个方法：<br />
findStudent(String id) :根据主键id找记录<br />
addStudent(Student student) ：添加一条记录<br />
<br />
在测试addStudent方法时候，我们准备添加如下一条数据<br />
<hr />
id name sex birthday<br />
0088 王耳朵 m 1982-01-01<br />
<hr />
那么在执行该方法后，数据库的student表里的数据是这样的：<br />
<hr />
id name sex birthday<br />
0001 翁仔 m 1979-12-31<br />
0002 王翠花 f 1982-08-09 <br />
0088 王耳朵 m 1982-01-01<br />
<hr />
<p>然后我们说明如何对这2个方法进行单元测试。<br />
<br />
实例展开<br />
1 把准备数据和预想数据转换成xml文件<br />
student_pre.xml<br />
<hr />
&lt;?xml version='1.0' encoding="gb2312"?&gt;<br />
&lt;dataset&gt;<br />
&lt;student id="0001" name="翁仔" sex="m" birthday="1979-12-31"/&gt;<br />
&lt;student id="0002" name="王翠花" sex="f" birthday="1982-08-09"/&gt;<br />
&lt;/dataset&gt;<br />
<hr />
<br />
student_exp.xml<br />
<hr />
&lt;?xml version='1.0' encoding="gb2312"?&gt;<br />
&lt;dataset&gt;<br />
&lt;student id="0001" name="翁仔" sex="m" birthday="1979-12-31"/&gt;<br />
&lt;student id="0002" name="王翠花" sex="f" birthday="1982-08-09"/&gt;<br />
&lt;student id="0088" name="王耳朵" sex="m" birthday="1982-01-01"/&gt;<br />
&lt;/dataset&gt;<br />
<hr />
<p>2 实装setUp方法，详细见代码注释。<br />
<hr />
protected void setUp() {<br />
IDatabaseConnection connection =null;<br />
try{<br />
super.setUp();<br />
//本例使用postgresql数据库 <br />
Class.forName("org.postgresql.Driver");<br />
//连接DB <br />
Connection conn=DriverManager.getConnection("jdbc:postgresql:testdb.test","postgres","postgres");<br />
//获得DB连接<br />
connection =new DatabaseConnection(conn);<br />
<br />
//对数据库中的操作对象表student进行备份<br />
QueryDataSet backupDataSet = new QueryDataSet(connection);<br />
backupDataSet.addTable("student");<br />
file=File.createTempFile("student_back",".xml");//备份文件<br />
FlatXmlDataSet.write(backupDataSet,new FileOutputStream(file));<br />
<br />
//准备数据的读入<br />
IDataSet dataSet = new FlatXmlDataSet( new FileInputStream("student_pre.xml"));<br />
DatabaseOperation.CLEAN_INSERT.execute(connection,dataSet);<br />
<br />
}catch(Exception e){<br />
e.printStackTrace();<br />
}finally{<br />
try{<br />
if(connection!=null) connection.close();<br />
}catch(SQLException e){}<br />
}<br />
}<br />
<hr />
3 实装测试方法，详细见代码注释。<br />
<br />
*检索类方法，可以利用assertEquals()方法，拿表的字段进行比较。<br />
<hr />
// findStudent <br />
public void testFindStudent() throws Exception{<br />
//执行findStudent方法<br />
StudentOpe studentOpe=new StudentOpe();<br />
Student result = studentOpe.findStudent("0001");<br />
<br />
//预想结果和实际结果的比较<br />
assertEquals("翁仔",result.getName());<br />
assertEquals("m",result.getSex());<br />
assertEquals("1979-12-31",result.getBirthDay());<br />
}<br />
<hr />
<br />
*更新，添加，删除等方法，可以利用Assertion.assertEquals()方法，拿表的整体来比较。<br />
<hr />
public void testAddStudent() throws Exception{<br />
//执行addStudent方法<br />
StudentOpe studentOpe=new StudentOpe();<br />
//被追加的记录<br />
Student newStudent = new Student("0088","王耳朵","m","1982-01-01");<br />
//执行追加方法 <br />
Student result = studentOpe.addStudent(newStudent);<br />
<br />
//预想结果和实际结果的比较<br />
IDatabaseConnection connection=null;<br />
<br />
try{<br />
<br />
//预期结果取得<br />
IDataSet expectedDataSet = new FlatXmlDataSet(new FileInputStream("student_exp.xml"));<br />
ITable expectedTable = expectedDataSet.getTable("student");<br />
<br />
//实际结果取得<br />
Connection conn=getConnection();<br />
connection =new DatabaseConnection(conn);<br />
<br />
IDataSet databaseDataSet = connection.createDataSet();<br />
ITable actualTable = databaseDataSet.getTable("student");<br />
<br />
//比较<br />
Assertion.assertEquals(expectedTable, actualTable);<br />
<br />
}finally{<br />
if(connection!=null) connection.close();<br />
}<br />
}<br />
<hr />
<br />
*如果在整体比较表的时候，有个别字段不需要比较，可以用DefaultColumnFilter.excludedColumnsTable()方法，<br />
将指定字段给排除在比较范围之外。比如上例中不需要比较birthday这个字段的话，那么可以如下代码所示进行处理：<br />
<hr />
ITable filteredExpectedTable = DefaultColumnFilter.excludedColumnsTable(expectedTable, new String[]{"birthday"});<br />
ITable filteredActualTable = DefaultColumnFilter.excludedColumnsTable(actualTable,new String[]{"birthday"});<br />
Assertion.assertEquals(filteredExpectedTable, filteredActualTable);<br />
<hr />
<br />
4 在tearDown()方法里边,把数据库还原到测试前状态<br />
<hr />
protected void tearDown() throws Exception{<br />
<br />
IDatabaseConnection connection =null;<br />
try{<br />
super.tearDown();<br />
Connection conn=getConnection();<br />
connection =new DatabaseConnection(conn);<br />
<br />
IDataSet dataSet = new FlatXmlDataSet(file);<br />
DatabaseOperation.CLEAN_INSERT.execute(connection,dataSet);<br />
<br />
}catch(Exception e){<br />
e.printStackTrace();<br />
}finally{<br />
try{<br />
if(connection!=null) connection.close();<br />
}catch(SQLException e){}<br />
}<br />
<br />
}<br />
<hr />
<br />
最后<br />
无疑，使用DbUnit能够极大的提高数据库测试的效率，希望通过本文能够让您掌握这一数据库测试的利器
<img src ="http://www.blogjava.net/liuzheng/aggbug/190128.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/liuzheng/" target="_blank">刘铮 </a> 2008-04-01 16:30 <a href="http://www.blogjava.net/liuzheng/articles/190128.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>