﻿<?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-JAVA学习随笔-随笔分类-测试</title><link>http://www.blogjava.net/wangzhouyu/category/22142.html</link><description /><language>zh-cn</language><lastBuildDate>Tue, 09 Mar 2010 16:32:59 GMT</lastBuildDate><pubDate>Tue, 09 Mar 2010 16:32:59 GMT</pubDate><ttl>60</ttl><item><title>Unitils开发指南（三）</title><link>http://www.blogjava.net/wangzhouyu/archive/2008/08/25/224169.html</link><dc:creator>小小~咖啡豆</dc:creator><author>小小~咖啡豆</author><pubDate>Mon, 25 Aug 2008 07:11:00 GMT</pubDate><guid>http://www.blogjava.net/wangzhouyu/archive/2008/08/25/224169.html</guid><wfw:comment>http://www.blogjava.net/wangzhouyu/comments/224169.html</wfw:comment><comments>http://www.blogjava.net/wangzhouyu/archive/2008/08/25/224169.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.blogjava.net/wangzhouyu/comments/commentRss/224169.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/wangzhouyu/services/trackbacks/224169.html</trackback:ping><description><![CDATA[<p class="0" style="margin-top: 5pt; text-align: justify;"><span style="font-weight: bold; font-size: 15pt; font-family: 'Times New Roman';"><font face="宋体">数据库测试</font></span><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><o:p></o:p></span></p>
<p class="0" style="text-align: justify;"><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><font face="宋体">在创建企业级应用的时候，数据层的单元测试因为其复杂性往往被遗弃，Unitils大大降低了测试的复杂性，使得数据库的测试变得容易并且易维护。已下介绍databasemodule和dbunitmodule进行数据库的单元测试。</font></span><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><o:p></o:p></span></p>
<p class="0" style="text-align: justify;"><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><o:p></o:p></span></p>
<p class="0" style="text-align: justify;"><span style="font-weight: bold; font-size: 14pt; font-family: 'Times New Roman';"><font face="宋体">用dbUnit管理测试数据</font></span><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><o:p></o:p></span></p>
<p class="0" style="text-align: justify;"><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><font face="宋体">数据库的测试应该在单元测试数据库上运行，单元测试数据库给我们提供了一个完整的并有着很好细粒度控制的测试数据，DbUnitModule是在dbunit的基础上进一步的为数据库的测试提供数据集的支持。</font></span><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><o:p></o:p></span></p>
<p class="0" style="text-align: justify;"><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><o:p></o:p></span></p>
<p class="0" style="text-align: justify;"><span style="font-style: italic; font-size: 14pt; font-family: 'Times New Roman';"><font face="宋体">加载测试数据集</font></span><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><o:p></o:p></span></p>
<p class="0" style="text-align: justify;"><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><font face="宋体">让我们以UserDAO中一个简单的方法findByName（检查姓氏和名字）为例子开始介绍。他的单元测试如下:</font></span><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><o:p></o:p></span></p>
<p class="0" style="margin-left: 22.5pt; text-align: justify;"><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><o:p></o:p></span></p>
<p class="0" style="margin-bottom: 5pt; margin-top: 5pt;"><span style="font-size: 10.5pt; font-family: 'Times New Roman';">@DataSet</span><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><o:p></o:p></span></p>
<p class="0" style="text-align: justify;"><span style="font-size: 10.5pt; font-family: 'Times New Roman';">public&nbsp;class&nbsp;UserDAOTest&nbsp;extends&nbsp;UnitilsJUnit4&nbsp;{</span><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><o:p></o:p></span></p>
<p class="0" style="text-align: justify;"><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><o:p></o:p></span></p>
<p class="0" style="text-align: justify;"><span style="font-size: 10.5pt; font-family: 'Times New Roman';">&nbsp;&nbsp;&nbsp;&nbsp;@Test</span><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><o:p></o:p></span></p>
<p class="0" style="text-align: justify;"><span style="font-size: 10.5pt; font-family: 'Times New Roman';">&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;void&nbsp;testFindByName()&nbsp;{</span><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><o:p></o:p></span></p>
<p class="0" style="text-align: justify;"><span style="font-size: 10.5pt; font-family: 'Times New Roman';">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;User&nbsp;result&nbsp;=&nbsp;userDao.findByName("doe",&nbsp;"john");</span><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><o:p></o:p></span></p>
<p class="0" style="text-align: justify;"><span style="font-size: 10.5pt; font-family: 'Times New Roman';">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;assertPropertyLenEquals("userName",&nbsp;"jdoe",&nbsp;result);</span><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><o:p></o:p></span></p>
<p class="0" style="text-align: justify;"><span style="font-size: 10.5pt; font-family: 'Times New Roman';">&nbsp;&nbsp;&nbsp;&nbsp;}</span><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><o:p></o:p></span></p>
<p class="0" style="text-align: justify;"><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><o:p></o:p></span></p>
<p class="0" style="text-align: justify;"><span style="font-size: 10.5pt; font-family: 'Times New Roman';">&nbsp;&nbsp;&nbsp;&nbsp;@Test</span><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><o:p></o:p></span></p>
<p class="0" style="text-align: justify;"><span style="font-size: 10.5pt; font-family: 'Times New Roman';">&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;void&nbsp;testFindByMinimalAge()&nbsp;{</span><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><o:p></o:p></span></p>
<p class="0" style="text-align: justify;"><span style="font-size: 10.5pt; font-family: 'Times New Roman';">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;List&lt;User&gt;&nbsp;result&nbsp;=&nbsp;userDao.findByMinimalAge(18);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><o:p></o:p></span></p>
<p class="0" style="text-align: justify;"><span style="font-size: 10.5pt; font-family: 'Times New Roman';">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;assertPropertyLenEquals("firstName",&nbsp;Arrays.asList("jack"),&nbsp;result);</span><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><o:p></o:p></span></p>
<p class="0" style="text-align: justify;"><span style="font-size: 10.5pt; font-family: 'Times New Roman';">&nbsp;&nbsp;&nbsp;&nbsp;}</span><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><o:p></o:p></span></p>
<p class="0" style="text-align: justify;"><span style="font-size: 10.5pt; font-family: 'Times New Roman';">}</span><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><o:p></o:p></span></p>
<p class="0" style="text-align: justify;"><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><o:p></o:p></span></p>
<p class="0" style="margin-bottom: 5pt; margin-top: 5pt;"><span style="font-size: 10.5pt; font-family: 'Times New Roman';">&nbsp;&nbsp;&nbsp;&nbsp;@DateSet&nbsp;<font face="宋体">注解表示了测试需要寻找dbunit的数据集文件进行加载，如果没有指明数据集的文件名，则Unitils自动在class文件的同目录下加载文件名为&nbsp;className.xml的数据集文件。（这种定义到class上面的数据集称为class级别的数据集）</font></span><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><o:p></o:p></span></p>
<p class="0" style="text-align: justify;"><span style="font-size: 10.5pt; font-family: 'Times New Roman';">&nbsp;&nbsp;&nbsp;&nbsp;<font face="宋体">数据集&nbsp;文件必须是dbunit的FlatXMLDataSet文件格式，其中包含了所要测试的数据。测试数据库表中所有的内容将会被删除，然后再插入数据集中的&nbsp;数据。如果表不属于数据集中的，哪么该表的数据将不会被删除。你也可以明确的加入一个空的表元素，例如&lt;MY_TABLE/&gt;（可以达到删除&nbsp;测试数据库表中内容的作用），如果要明确指定一个空的值，那么使用值[null]。</font></span><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><o:p></o:p></span></p>
<p class="0" style="text-align: justify;"><span style="font-size: 10.5pt; font-family: 'Times New Roman';">&nbsp;&nbsp;&nbsp;<font face="宋体">为UserDAOTest我们创建一个数据集，并放在UserDAOTest.class文件同目录下。</font></span><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><o:p></o:p></span></p>
<p class="0" style="margin-left: 22.5pt; text-align: justify;"><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><o:p></o:p></span></p>
<p class="0" style="margin-bottom: 5pt; margin-top: 5pt;"><span style="font-size: 10.5pt; font-family: 'Times New Roman';">&lt;?xml&nbsp;version='1.0'&nbsp;encoding='UTF-8'?&gt;</span><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><o:p></o:p></span></p>
<p class="0" style="text-align: justify;"><span style="font-size: 10.5pt; font-family: 'Times New Roman';">&lt;dataset&gt;</span><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><o:p></o:p></span></p>
<p class="0" style="text-align: justify;"><span style="font-size: 10.5pt; font-family: 'Times New Roman';">&nbsp;&nbsp;&nbsp;&nbsp;&lt;usergroup&nbsp;name="admin"&nbsp;/&gt;&nbsp;&nbsp;</span><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><o:p></o:p></span></p>
<p class="0" style="text-align: justify;"><span style="font-size: 10.5pt; font-family: 'Times New Roman';">&nbsp;&nbsp;&nbsp;&nbsp;&lt;user&nbsp;userName="jdoe"&nbsp;&nbsp;name="doe"&nbsp;&nbsp;&nbsp;firstname="john"&nbsp;&nbsp;&nbsp;userGroup="admin"&nbsp;/&gt;</span><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><o:p></o:p></span></p>
<p class="0" style="text-align: justify;"><span style="font-size: 10.5pt; font-family: 'Times New Roman';">&nbsp;&nbsp;&nbsp;&nbsp;&lt;usergroup&nbsp;name="sales"&nbsp;/&gt;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><o:p></o:p></span></p>
<p class="0" style="text-align: justify;"><span style="font-size: 10.5pt; font-family: 'Times New Roman';">&nbsp;&nbsp;&nbsp;&nbsp;&lt;user&nbsp;userName="smith"&nbsp;name="smith"&nbsp;userGroup="sales"&nbsp;/&gt;</span><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><o:p></o:p></span></p>
<p class="0" style="text-align: justify;"><span style="font-size: 10.5pt; font-family: 'Times New Roman';">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><o:p></o:p></span></p>
<p class="0" style="text-align: justify;"><span style="font-size: 10.5pt; font-family: 'Times New Roman';">&lt;/dataset&gt;</span><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><o:p></o:p></span></p>
<p class="0" style="margin-bottom: 5pt; margin-top: 5pt;"><span style="font-size: 10.5pt; font-family: 'Times New Roman';">&nbsp;&nbsp;&nbsp;<font face="宋体">测试运行的时候，首先将删除掉usergroup表和user表中的所有内容，然后将插入数据集中的内容。其中name为smith的firstname的值将会是null。</font></span><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><o:p></o:p></span></p>
<p class="0" style="text-align: justify;"><span style="font-size: 10.5pt; font-family: 'Times New Roman';">&nbsp;&nbsp;&nbsp;<font face="宋体">假设testFindByMinimalAge()方法将使用一个特殊的数据集而不是使用class级别的数据集，你可以定义一个</font></span><span style="font-style: italic; font-size: 10.5pt; font-family: 'Times New Roman';">UserDAOTest.testFindByMinimalAge.xml</span><span style="font-size: 10.5pt; font-family: 'Times New Roman';">&nbsp;<font face="宋体">数据集文件并放在测试类的class文件同目录下。</font></span><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><o:p></o:p></span></p>
<p class="0" style="margin-left: 22.5pt; text-align: justify;"><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><o:p></o:p></span></p>
<p class="0" style="margin-bottom: 5pt; margin-top: 5pt;"><span style="font-size: 10.5pt; font-family: 'Times New Roman';">&lt;?xml&nbsp;version='1.0'&nbsp;encoding='UTF-8'?&gt;</span><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><o:p></o:p></span></p>
<p class="0" style="text-align: justify;"><span style="font-size: 10.5pt; font-family: 'Times New Roman';">&lt;dataset&gt;</span><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><o:p></o:p></span></p>
<p class="0" style="text-align: justify;"><span style="font-size: 10.5pt; font-family: 'Times New Roman';">&nbsp;&nbsp;&nbsp;&nbsp;&lt;user&nbsp;userName="jack"&nbsp;age="18"&nbsp;/&gt;</span><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><o:p></o:p></span></p>
<p class="0" style="text-align: justify;"><span style="font-size: 10.5pt; font-family: 'Times New Roman';">&nbsp;&nbsp;&nbsp;&nbsp;&lt;user&nbsp;userName="jim"&nbsp;&nbsp;age="17"&nbsp;/&gt;</span><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><o:p></o:p></span></p>
<p class="0" style="text-align: justify;"><span style="font-size: 10.5pt; font-family: 'Times New Roman';">&lt;/dataset&gt;</span><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><o:p></o:p></span></p>
<p class="0" style="text-align: justify;"><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><o:p></o:p></span></p>
<p class="0" style="margin-bottom: 5pt; margin-top: 5pt;"><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><font face="宋体">这时，你在testFindByMinimalAge()方法使用@DataSet注解，他将覆盖class级的数据集</font></span><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><o:p></o:p></span></p>
<p class="0" style="margin-left: 22.5pt; text-align: justify;"><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><o:p></o:p></span></p>
<p class="0" style="margin-bottom: 5pt; margin-top: 5pt;"><span style="font-size: 10.5pt; font-family: 'Times New Roman';">public&nbsp;class&nbsp;UserDAOTest&nbsp;extends&nbsp;UnitilsJUnit4&nbsp;{</span><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><o:p></o:p></span></p>
<p class="0" style="text-indent: 21pt; text-align: justify;"><span style="font-size: 10.5pt; font-family: 'Times New Roman';">@Test</span><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><o:p></o:p></span></p>
<p class="0" style="text-indent: 21pt; text-align: justify;"><span style="font-size: 10.5pt; font-family: 'Times New Roman';">@DataSet("UserDAOTest.testFindByMinimalAge.xml")</span><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><o:p></o:p></span></p>
<p class="0" style="text-indent: 21pt; text-align: justify;"><span style="font-size: 10.5pt; font-family: 'Times New Roman';">public&nbsp;void&nbsp;testFindByMinimalAge()&nbsp;{</span><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><o:p></o:p></span></p>
<p class="0" style="margin-left: 21pt; text-indent: 21pt; text-align: justify;"><span style="font-size: 10.5pt; font-family: 'Times New Roman';">List&lt;User&gt;&nbsp;result&nbsp;=&nbsp;userDao.findByMinimalAge(18);&nbsp;</span><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><o:p></o:p></span></p>
<p class="0" style="margin-left: 21pt; text-indent: 21pt; text-align: justify;"><span style="font-size: 10.5pt; font-family: 'Times New Roman';">assertPropertyLenEquals("firstName",&nbsp;Arrays.asList("jack"),&nbsp;result);</span><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><o:p></o:p></span></p>
<p class="0" style="text-indent: 21pt; text-align: justify;"><span style="font-size: 10.5pt; font-family: 'Times New Roman';">}</span><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><o:p></o:p></span></p>
<p class="0" style="text-align: justify;"><span style="font-size: 10.5pt; font-family: 'Times New Roman';">}</span><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><o:p></o:p></span></p>
<p class="0" style="text-align: justify;"><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><o:p></o:p></span></p>
<p class="0" style="margin-bottom: 5pt; margin-top: 5pt;"><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><font face="宋体">不要过多的使用method级的数据集，因为过多的数据集文件意味着你要花大量的时间去维护，你优先考虑的是使用class级的数据集。</font></span><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><o:p></o:p></span></p>
<p class="0" style="margin-bottom: 5pt; margin-top: 5pt;"><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><o:p></o:p></span></p>
<p class="0" style="margin-bottom: 5pt; margin-top: 5pt;"><span style="font-style: italic; font-size: 14pt; font-family: '宋体';"><font face="宋体">配置数据集加载策略</font></span><span style="font-size: 10.5pt; font-family: '宋体';"><o:p></o:p></span></p>
<p class="0" style="margin-bottom: 5pt; margin-top: 5pt;"><span style="font-size: 10.5pt; font-family: '宋体';"><font face="宋体">缺省情况下数据集被写入数据库采用的是</font></span><span style="font-style: italic; font-size: 10.5pt; font-family: '宋体';">clean&nbsp;insert</span><span style="font-size: 10.5pt; font-family: '宋体';"><font face="宋体">策略。这就意味着数据在被写入数据库的时候是会先删除数据集中有使用的表的数据，然后在将数据集中的数据写入数据库。加载策略是可配额制的，我们通过修改</font></span><span style="font-style: italic; font-size: 10.5pt; font-family: 'Times New Roman';">DbUnitModule.DataSet.loadStrategy.default</span><span style="font-size: 10.5pt; font-family: 'Times New Roman';">&nbsp;<font face="宋体">的属性值来改变加载策略。假设我们在unitils.properties属性文件中加入以下内容：</font></span><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><o:p></o:p></span></p>
<p class="0" style="margin-top: 5pt; text-align: justify;"><span style="font-size: 10.5pt; font-family: 'Times New Roman';">DbUnitModule.DataSet.loadStrategy.default=org.unitils.dbunit.datasetloadstrategy.InsertLoadStrategy&nbsp;</span><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><o:p></o:p></span></p>
<p class="0" style="margin-bottom: 5pt; margin-top: 5pt;"><span style="font-size: 10.5pt; font-family: '宋体';"><font face="宋体">这时加载策略就由</font></span><span style="font-style: italic; font-size: 10.5pt; font-family: '宋体';">clean&nbsp;insert</span><span style="font-size: 10.5pt; font-family: '宋体';"><font face="宋体">变成了</font></span><span style="font-style: italic; font-size: 10.5pt; font-family: '宋体';">insert</span><span style="font-size: 10.5pt; font-family: '宋体';"><font face="宋体">，数据已经存在表中将不会被删除，测试数据只是进行插入操作。</font></span><span style="font-size: 10.5pt; font-family: '宋体';"><o:p></o:p></span></p>
<p class="0"><span style="font-size: 10.5pt; font-family: '宋体';"><font face="宋体">加载策略也可以使用</font></span><span style="font-style: italic; font-size: 10.5pt; font-family: '宋体';">@DataSet</span><span style="font-size: 10.5pt; font-family: '宋体';"><font face="宋体">的注解属性对单独的一些测试进行配置：</font></span><span style="font-size: 10.5pt; font-family: '宋体';"><o:p></o:p></span></p>
<p class="0" style="margin-top: 5pt; text-align: justify;"><span style="font-size: 10.5pt; font-family: 'Times New Roman';">@DataSet(loadStrategy&nbsp;=&nbsp;InsertLoadStrategy.class)&nbsp;</span><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><o:p></o:p></span></p>
<p class="0"><span style="font-size: 10.5pt; font-family: '宋体';"><o:p></o:p></span></p>
<p class="0"><span style="font-size: 10.5pt; font-family: '宋体';"><font face="宋体">对于那些树形DbUnit的人来说，配置加载策略实际上就是使用不同的</font></span><span style="font-size: 10.5pt; font-family: 'Times New Roman';">DatabaseOperation<font face="宋体">，以下是默认支持的加载策略方式：</font></span><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><o:p></o:p></span></p>
<p class="0" style="margin-left: 21pt; text-indent: -21pt; margin-top: 5pt; text-align: justify;"><span style="font-size: 10.5pt; font-family: 'Wingdings';">l&nbsp;</span><span style="font-size: 10.5pt; font-family: 'Times New Roman';">CleanInsertLoadStrategy:&nbsp;<font face="宋体">先删除dateSet中有关表的数据，然后再插入数据。</font></span><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><o:p></o:p></span></p>
<p class="0" style="margin-left: 21pt; text-indent: -21pt;"><span style="font-size: 10.5pt; font-family: 'Wingdings';">l&nbsp;</span><span style="font-size: 10.5pt; font-family: 'Times New Roman';">InsertLoadStrategy:&nbsp;<font face="宋体">只插入数据。</font></span><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><o:p></o:p></span></p>
<p class="0" style="margin-left: 21pt; text-indent: -21pt;"><span style="font-size: 10.5pt; font-family: 'Wingdings';">l&nbsp;</span><span style="font-size: 10.5pt; font-family: 'Times New Roman';">RefreshLoadStrategy:&nbsp;<font face="宋体">有同样key的数据更新，没有的插入。</font></span><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><o:p></o:p></span></p>
<p class="0" style="margin-left: 21pt; text-indent: -21pt;"><span style="font-size: 10.5pt; font-family: 'Wingdings';">l&nbsp;</span><span style="font-size: 10.5pt; font-family: 'Times New Roman';">UpdateLoadStrategy:&nbsp;<font face="宋体">有同样key的数据更新，没有的不做任何操作。</font></span><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><o:p></o:p></span></p>
<p class="0" style="text-align: justify;"><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><o:p></o:p></span></p>
<p class="0" style="text-align: justify;"><span style="font-style: italic; font-size: 14pt; font-family: 'Times New Roman';"><font face="宋体">配置数据集工厂</font></span><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><o:p></o:p></span></p>
<p class="0" style="text-align: justify;"><span style="font-size: 10.5pt; font-family: 'Times New Roman';">&nbsp;</span><span style="font-size: 10.5pt; font-family: '宋体';"><font face="宋体">在Unitils中数据集文件采用了</font></span><span style="font-style: italic; font-size: 10.5pt; font-family: 'Times New Roman';">multischema&nbsp;xml</span><span style="font-size: 10.5pt; font-family: 'Times New Roman';">&nbsp;<font face="宋体">格式，这是DbUnits的</font></span><span style="font-style: italic; font-size: 10.5pt; font-family: 'Times New Roman';">FlatXmlDataSet</span><span style="font-size: 10.5pt; font-family: 'Times New Roman';">&nbsp;<font face="宋体">格式的扩展。配置文件格式和文件的扩展可以采用</font></span><span style="font-style: italic; font-size: 10.5pt; font-family: 'Times New Roman';">DataSetFactory</span><span style="font-size: 10.5pt; font-family: 'Times New Roman';">&nbsp;<font face="宋体">。</font></span><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><o:p></o:p></span></p>
<p class="0" style="text-align: justify;"><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><font face="宋体">虽然Unitils当前只支持一种数据格式，但是我们可以通过实现</font></span><span style="font-style: italic; font-size: 10.5pt; font-family: 'Times New Roman';">DataSetFactory</span><span style="font-style: normal; font-size: 10.5pt; font-family: 'Times New Roman';"><font face="宋体">来使用其他文件格式。</font></span><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><font face="宋体">当你想使用excel而不是xml格式的时候，</font></span><span style="font-style: normal; font-size: 10.5pt; font-family: 'Times New Roman';"><font face="宋体">可以通过unitils.property中的</font></span><span style="font-style: italic; font-size: 10.5pt; font-family: 'Times New Roman';">DbUnitModule.DataSet.factory.default</span><span style="font-size: 10.5pt; font-family: 'Times New Roman';">&nbsp;<font face="宋体">属性和</font></span><span style="font-style: italic; font-size: 10.5pt; font-family: 'Times New Roman';">@DataSet</span><span style="font-size: 10.5pt; font-family: 'Times New Roman';">&nbsp;<font face="宋体">注解来创建一个DbUnit's&nbsp;</font></span><span style="font-style: italic; font-size: 10.5pt; font-family: 'Times New Roman';">XlsDataSet</span><span style="font-size: 10.5pt; font-family: 'Times New Roman';">&nbsp;<font face="宋体">实例。</font></span><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><o:p></o:p></span></p>
<p class="0" style="text-align: justify;"><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><o:p></o:p></span></p>
<p class="0" style="text-align: justify;"><span style="font-style: italic; font-size: 14pt; font-family: 'Times New Roman';"><font face="宋体">验证测试结果</font></span><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><o:p></o:p></span></p>
<p class="0" style="text-align: justify;"><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><font face="宋体">有些时候我们想在测试时完毕后使用数据集来检查数据库中的内容，举个例子当执行完毕一个存储过程后你想检查一下啊数据是否更新了没有。</font></span><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><o:p></o:p></span></p>
<p class="0" style="text-align: justify;"><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><font face="宋体">下面的例子表示的是禁用到一年内没有使用过的帐户</font></span><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><o:p></o:p></span></p>
<p class="0" style="margin-top: 5pt; text-align: justify;"><span style="font-size: 10.5pt; font-family: 'Times New Roman';">public&nbsp;class&nbsp;UserDAOTest&nbsp;extends&nbsp;UnitilsJUnit4&nbsp;{&nbsp;</span><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><o:p></o:p></span></p>
<p class="0" style="margin-top: 5pt; text-align: justify;"><span style="font-size: 10.5pt; font-family: 'Times New Roman';">&nbsp;&nbsp;&nbsp;&nbsp;@Test&nbsp;@ExpectedDataSet&nbsp;</span><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><o:p></o:p></span></p>
<p class="0" style="margin-top: 5pt; text-align: justify;"><span style="font-size: 10.5pt; font-family: 'Times New Roman';">&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;void&nbsp;testInactivateOldAccounts()&nbsp;{&nbsp;</span><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><o:p></o:p></span></p>
<p class="0" style="margin-top: 5pt; text-align: justify;"><span style="font-size: 10.5pt; font-family: 'Times New Roman';">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;userDao.inactivateOldAccounts();&nbsp;</span><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><o:p></o:p></span></p>
<p class="0" style="margin-top: 5pt; text-align: justify;"><span style="font-size: 10.5pt; font-family: 'Times New Roman';">&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</span><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><o:p></o:p></span></p>
<p class="0" style="margin-top: 5pt; text-align: justify;"><span style="font-size: 10.5pt; font-family: 'Times New Roman';">}&nbsp;</span><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><o:p></o:p></span></p>
<p class="0" style="margin-top: 5pt; text-align: justify;"><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><font face="宋体">注意在test方法上增加了一个</font></span><span style="font-style: italic; font-size: 10.5pt; font-family: 'Times New Roman';">@ExpectedDataSet</span><span style="font-size: 10.5pt; font-family: 'Times New Roman';">&nbsp;<font face="宋体">注解。这将指明unitils将使用</font></span><span style="font-style: italic; font-size: 10.5pt; font-family: 'Times New Roman';">UserDAOTest.testInactivateOldAccounts-result.xml</span><span style="font-size: 10.5pt; font-family: 'Times New Roman';">&nbsp;<font face="宋体">这个数据集的内容和数据库的内容进行比较。</font></span><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><o:p></o:p></span></p>
<p class="0" style="margin-top: 5pt; text-align: justify;"><span style="font-size: 10.5pt; font-family: 'Times New Roman';">&lt;?xml&nbsp;version='1.0'&nbsp;encoding='UTF-8'?&gt;&nbsp;</span><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><o:p></o:p></span></p>
<p class="0" style="margin-top: 5pt; text-align: justify;"><span style="font-size: 10.5pt; font-family: 'Times New Roman';">&lt;dataset&gt;&nbsp;</span><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><o:p></o:p></span></p>
<p class="0" style="margin-top: 5pt; text-align: justify;"><span style="font-size: 10.5pt; font-family: 'Times New Roman';">&nbsp;&nbsp;&nbsp;&nbsp;&lt;user&nbsp;userName="jack"&nbsp;active="true"&nbsp;/&gt;&nbsp;</span><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><o:p></o:p></span></p>
<p class="0" style="margin-top: 5pt; text-align: justify;"><span style="font-size: 10.5pt; font-family: 'Times New Roman';">&nbsp;&nbsp;&nbsp;&nbsp;&lt;user&nbsp;userName="jim"&nbsp;&nbsp;active="false"&nbsp;/&gt;&nbsp;</span><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><o:p></o:p></span></p>
<p class="0" style="margin-top: 5pt; text-align: justify;"><span style="font-size: 10.5pt; font-family: 'Times New Roman';">&lt;/dataset&gt;&nbsp;</span><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><o:p></o:p></span></p>
<p class="0" style="margin-top: 5pt; text-align: justify;"><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><font face="宋体">根据这个数据集，将会检查是否有两条和记录集的值相同的记录在数据库中。而其他的记录和表将不理会。</font></span><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><o:p></o:p></span></p>
<p class="0" style="margin-top: 5pt; text-align: justify;"><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><font face="宋体">使用的是</font></span><span style="font-style: italic; font-size: 10.5pt; font-family: 'Times New Roman';">@DataSet</span><span style="font-size: 10.5pt; font-family: 'Times New Roman';">&nbsp;<font face="宋体">注解的话，文件名可以明确指出，如果文件名没有明确指出来，那么文件名将匹配</font></span><span style="font-style: italic; font-size: 10.5pt; font-family: 'Times New Roman';">className</span><span style="font-size: 10.5pt; font-family: 'Times New Roman';">&nbsp;.</span><span style="font-style: italic; font-size: 10.5pt; font-family: 'Times New Roman';">methodName</span><span style="font-size: 10.5pt; font-family: 'Times New Roman';">&nbsp;-result.xml&nbsp;</span><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><o:p></o:p></span></p>
<p class="0" style="margin-top: 5pt; text-align: justify;"><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><font face="宋体">使用少使用结果数据集，加入新的数据集意味着更多的维护。替代方式是在代码中执行相同的检查（如使用一个findactiveusers()方法）。</font></span><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><o:p></o:p></span></p>
<p class="0" style="margin-top: 5pt; text-align: justify;"><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><o:p></o:p></span></p>
<p class="0" style="margin-top: 5pt; text-align: justify;"><span style="font-style: italic; font-size: 14pt; font-family: 'Times New Roman';"><font face="宋体">使用多模式的数据集</font></span><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><o:p></o:p></span></p>
<p class="0" style="margin-top: 5pt; text-align: justify;"><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><font face="宋体">一个程序不单单只是连接一个数据库shema。Unitils采用了扩展的数据集xml来定义多schemas下的数据。以下就是一个读取数据到2个不同的schemas中的例子：</font></span><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><o:p></o:p></span></p>
<p class="0" style="margin-top: 5pt; text-align: justify;"><span style="font-size: 10.5pt; font-family: 'Times New Roman';">&lt;?xml&nbsp;version='1.0'&nbsp;encoding='UTF-8'?&gt;&nbsp;</span><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><o:p></o:p></span></p>
<p class="0" style="margin-top: 5pt; text-align: justify;"><span style="font-size: 10.5pt; font-family: 'Times New Roman';">&lt;dataset&nbsp;xmlns="SCHEMA_A"&nbsp;xmlns:b="SCHEMA_B"&gt;&nbsp;</span><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><o:p></o:p></span></p>
<p class="0" style="margin-top: 5pt; text-align: justify;"><span style="font-size: 10.5pt; font-family: 'Times New Roman';">&nbsp;&nbsp;&nbsp;&nbsp;&lt;user&nbsp;id="1"&nbsp;userName="jack"&nbsp;/&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><o:p></o:p></span></p>
<p class="0" style="margin-top: 5pt; text-align: justify;"><span style="font-size: 10.5pt; font-family: 'Times New Roman';">&nbsp;&nbsp;&nbsp;&nbsp;&lt;b:role&nbsp;id="1"&nbsp;roleName="admin"&nbsp;/&gt;&nbsp;</span><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><o:p></o:p></span></p>
<p class="0" style="margin-top: 5pt; text-align: justify;"><span style="font-size: 10.5pt; font-family: 'Times New Roman';">&lt;/dataset&gt;&nbsp;</span><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><o:p></o:p></span></p>
<p class="0" style="margin-top: 5pt; text-align: justify;"><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><font face="宋体">在这个例子中我定义了两个schemas，</font></span><span style="font-style: italic; font-size: 10.5pt; font-family: 'Times New Roman';">SCHEMA_A</span><span style="font-size: 10.5pt; font-family: 'Times New Roman';">&nbsp;<font face="宋体">和&nbsp;</font></span><span style="font-style: italic; font-size: 10.5pt; font-family: 'Times New Roman';">SCHEMA_B<font face="宋体">。</font></span><span style="font-style: normal; font-size: 10.5pt; font-family: 'Times New Roman';"><font face="宋体">第一个schema，</font></span><span style="font-style: italic; font-size: 10.5pt; font-family: 'Times New Roman';">SCHEMA_A</span><span style="font-size: 10.5pt; font-family: 'Times New Roman';">&nbsp;<font face="宋体">被连接到默认的xml命名空间中，第二个schema，</font></span><span style="font-style: italic; font-size: 10.5pt; font-family: 'Times New Roman';">SCHEMA_B</span><span style="font-size: 10.5pt; font-family: 'Times New Roman';">&nbsp;<font face="宋体">被连接到命名空间b。如果表xml元素的前缀使用了命名空间b，那么该表就是schema&nbsp;</font></span><span style="font-style: italic; font-size: 10.5pt; font-family: 'Times New Roman';">SCHEMA_B</span><span style="font-size: 10.5pt; font-family: 'Times New Roman';">&nbsp;<font face="宋体">中的，如果没有使用任何的命名空间那么该表将被认为是</font></span><span style="font-style: italic; font-size: 10.5pt; font-family: 'Times New Roman';">SCHEMA_A</span><span style="font-size: 10.5pt; font-family: 'Times New Roman';">&nbsp;&nbsp;</span><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><o:p></o:p></span></p>
<p class="0" style="text-align: justify;"><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><font face="宋体">中的。以上例子中测试数据定义了表</font></span><span style="font-style: italic; font-size: 10.5pt; font-family: 'Times New Roman';">SCHEMA_A.user</span><span style="font-size: 10.5pt; font-family: 'Times New Roman';">&nbsp;<font face="宋体">和</font></span><span style="font-style: italic; font-size: 10.5pt; font-family: 'Times New Roman';">SCHEMA_B.role<font face="宋体">。</font></span><span style="font-style: italic; font-size: 10.5pt; font-family: 'Times New Roman';"><o:p></o:p></span></p>
<p class="0" style="text-align: justify;"><span style="font-style: italic; font-size: 10.5pt; font-family: 'Times New Roman';"><o:p></o:p></span></p>
<p class="0" style="text-align: justify;"><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><font face="宋体">如果在数据集中没有配置一个默认的命名空间，那么将会采用在unitils.properties中的属性</font></span><span style="font-style: italic; font-size: 10.5pt; font-family: 'Times New Roman';">database.schemaNames</span><span style="font-size: 10.5pt; font-family: 'Times New Roman';">&nbsp;<font face="宋体">的第一个值作为默认的</font></span><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><o:p></o:p></span></p>
<p class="0" style="text-align: justify;"><span style="font-size: 10.5pt; font-family: 'Times New Roman';">database.schemaNames=SCHEMA_A,&nbsp;SCHEMA_B&nbsp;</span><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><o:p></o:p></span></p>
<p class="0" style="text-align: justify;"><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><font face="宋体">这个配置将</font></span><span style="font-style: italic; font-size: 10.5pt; font-family: 'Times New Roman';">SCHEMA_A</span><span style="font-size: 10.5pt; font-family: 'Times New Roman';">&nbsp;<font face="宋体">作为缺省的schema，这样你可以简化数据集的声明。</font></span><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><o:p></o:p></span></p>
<p class="0" style="margin-top: 5pt; text-align: justify;"><span style="font-size: 10.5pt; font-family: 'Times New Roman';">&lt;?xml&nbsp;version='1.0'&nbsp;encoding='UTF-8'?&gt;&nbsp;</span><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><o:p></o:p></span></p>
<p class="0" style="margin-top: 5pt; text-align: justify;"><span style="font-size: 10.5pt; font-family: 'Times New Roman';">&lt;dataset&nbsp;xmlns:b="SCHEMA_B"&gt;&nbsp;</span><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><o:p></o:p></span></p>
<p class="0" style="margin-top: 5pt; text-align: justify;"><span style="font-size: 10.5pt; font-family: 'Times New Roman';">&nbsp;&nbsp;&nbsp;&nbsp;&lt;user&nbsp;id="1"&nbsp;userName="jack"&nbsp;/&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><o:p></o:p></span></p>
<p class="0" style="margin-top: 5pt; text-align: justify;"><span style="font-size: 10.5pt; font-family: 'Times New Roman';">&nbsp;&nbsp;&nbsp;&nbsp;&lt;b:role&nbsp;id="1"&nbsp;roleName="admin"&nbsp;/&gt;&nbsp;</span><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><o:p></o:p></span></p>
<p class="0" style="margin-top: 5pt; text-align: justify;"><span style="font-size: 10.5pt; font-family: 'Times New Roman';">&lt;/dataset&gt;&nbsp;</span><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><o:p></o:p></span></p>
<p class="0" style="text-align: justify;"><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><o:p></o:p></span></p>
<p class="0" style="text-align: justify;"><span style="font-style: italic; font-size: 14pt; font-family: 'Times New Roman';"><font face="宋体">连接测试数据库</font></span><span style="font-size: 10.5pt; font-family: 'Times New Roman';">&nbsp;</span><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><o:p></o:p></span></p>
<p class="0" style="text-align: justify;"><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><font face="宋体">在以上所有的例子中，我们都有一件重要的事情没有做：当我们进行测试的时候，怎样连接数据库并得到</font></span><span style="font-style: italic; font-size: 10.5pt; font-family: 'Times New Roman';">DataSource<font face="宋体">？</font></span><span style="font-style: italic; font-size: 10.5pt; font-family: 'Times New Roman';"><o:p></o:p></span></p>
<p class="0" style="text-align: justify;"><span style="font-style: normal; font-size: 10.5pt; font-family: 'Times New Roman';"><font face="宋体">当测试套件的第一个测试数据库的案例运行的时候，Unitils将会通过属性文件创建一个</font></span><span style="font-style: italic; font-size: 10.5pt; font-family: 'Times New Roman';">DataSource</span><span style="font-size: 10.5pt; font-family: 'Times New Roman';">&nbsp;<font face="宋体">的实例来连接你单元测试时的数据库，以后的测试中都将使用这个</font></span><span style="font-style: italic; font-size: 10.5pt; font-family: 'Times New Roman';">DataSource</span><span style="font-size: 10.5pt; font-family: 'Times New Roman';">&nbsp;<font face="宋体">实例。连接配置的详细内容如下：</font></span><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><o:p></o:p></span></p>
<p class="0" style="margin-top: 5pt; text-align: justify;"><span style="font-size: 10.5pt; font-family: 'Times New Roman';">database.driverClassName=oracle.jdbc.driver.OracleDriver&nbsp;</span><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><o:p></o:p></span></p>
<p class="0" style="margin-top: 5pt; text-align: justify;"><span style="font-size: 10.5pt; font-family: 'Times New Roman';">database.url=jdbc:oracle:thin:@yourmachine:1521:YOUR_DB&nbsp;</span><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><o:p></o:p></span></p>
<p class="0" style="margin-top: 5pt; text-align: justify;"><span style="font-size: 10.5pt; font-family: 'Times New Roman';">database.userName=john&nbsp;</span><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><o:p></o:p></span></p>
<p class="0" style="margin-top: 5pt; text-align: justify;"><span style="font-size: 10.5pt; font-family: 'Times New Roman';">database.password=secret&nbsp;</span><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><o:p></o:p></span></p>
<p class="0" style="margin-top: 5pt; text-align: justify;"><span style="font-size: 10.5pt; font-family: 'Times New Roman';">database.schemaNames=test_john&nbsp;</span><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><o:p></o:p></span></p>
<p class="0" style="text-align: justify;"><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><o:p></o:p></span></p>
<p class="0" style="text-align: justify;"><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><font face="宋体">按</font></span><span style="font-weight: bold; font-size: 10.5pt; font-family: 'Times New Roman';"><font face="宋体">配置</font></span><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><font face="宋体">章节所说的那样，你可以将连接数据库的驱动类和url地址配置到</font></span><span style="font-style: italic; font-size: 10.5pt; font-family: 'Times New Roman';">unitils.properties</span><span style="font-size: 10.5pt; font-family: 'Times New Roman';">&nbsp;<font face="宋体">中去，而用户名，密码以及schema可以配置到</font></span><span style="font-style: italic; font-size: 10.5pt; font-family: 'Times New Roman';">unitils-local.properties</span><span style="font-size: 10.5pt; font-family: 'Times New Roman';">&nbsp;<font face="宋体">中去，这样可以让开发人员连接到自己的单元测试数据库中进行测试而不会干预到其他的人。</font></span><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><o:p></o:p></span></p>
<p class="0" style="text-align: justify;"><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><o:p></o:p></span></p>
<p class="0" style="text-align: justify;"><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><font face="宋体">在属性或者setter方法前使用注解</font></span><span style="font-style: italic; font-size: 10.5pt; font-family: 'Times New Roman';">@TestDataSource</span><span style="font-size: 10.5pt; font-family: 'Times New Roman';">&nbsp;<font face="宋体">，将会将</font></span><span style="font-style: italic; font-size: 10.5pt; font-family: 'Times New Roman';">DataSource</span><span style="font-size: 10.5pt; font-family: 'Times New Roman';">&nbsp;<font face="宋体">实例注入到测试实例中去，如果你想加入一些代码或者配置一下你的datasource，你可以做一个抽象类来实现该功能，所有的测试类都继承该类。一个简单的例子如下：</font></span><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><o:p></o:p></span></p>
<p class="0" style="margin-top: 5pt; text-align: justify;"><span style="font-size: 10.5pt; font-family: 'Times New Roman';">public&nbsp;abstract&nbsp;class&nbsp;BaseDAOTest&nbsp;extends&nbsp;UnitilsJUnit4&nbsp;{&nbsp;</span><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><o:p></o:p></span></p>
<p class="0" style="margin-top: 5pt; text-align: justify;"><span style="font-size: 10.5pt; font-family: 'Times New Roman';">&nbsp;&nbsp;&nbsp;&nbsp;@TestDataSource&nbsp;</span><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><o:p></o:p></span></p>
<p class="0" style="margin-top: 5pt; text-align: justify;"><span style="font-size: 10.5pt; font-family: 'Times New Roman';">&nbsp;&nbsp;&nbsp;&nbsp;private&nbsp;DataSource&nbsp;dataSource;&nbsp;</span><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><o:p></o:p></span></p>
<p class="0" style="margin-top: 5pt; text-align: justify;"><span style="font-size: 10.5pt; font-family: 'Times New Roman';">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><o:p></o:p></span></p>
<p class="0" style="margin-top: 5pt; text-align: justify;"><span style="font-size: 10.5pt; font-family: 'Times New Roman';">&nbsp;&nbsp;&nbsp;&nbsp;@Before&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><o:p></o:p></span></p>
<p class="0" style="margin-top: 5pt; text-align: justify;"><span style="font-size: 10.5pt; font-family: 'Times New Roman';">&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;void&nbsp;initializeDao()&nbsp;{&nbsp;</span><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><o:p></o:p></span></p>
<p class="0" style="margin-top: 5pt; text-align: justify;"><span style="font-size: 10.5pt; font-family: 'Times New Roman';">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;BaseDAO&nbsp;dao&nbsp;=&nbsp;getDaoUnderTest();&nbsp;</span><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><o:p></o:p></span></p>
<p class="0" style="margin-top: 5pt; text-align: justify;"><span style="font-size: 10.5pt; font-family: 'Times New Roman';">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dao.setDataSource(dataSource);&nbsp;</span><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><o:p></o:p></span></p>
<p class="0" style="margin-top: 5pt; text-align: justify;"><span style="font-size: 10.5pt; font-family: 'Times New Roman';">&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</span><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><o:p></o:p></span></p>
<p class="0" style="margin-top: 5pt; text-align: justify;"><span style="font-size: 10.5pt; font-family: 'Times New Roman';">&nbsp;&nbsp;&nbsp;&nbsp;protected&nbsp;abstract&nbsp;BaseDAO&nbsp;getDaoUnderTest();&nbsp;</span><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><o:p></o:p></span></p>
<p class="0" style="text-align: justify;"><span style="font-size: 10.5pt; font-family: 'Times New Roman';">}&nbsp;</span><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><o:p></o:p></span></p>
<p class="0" style="text-align: justify;"><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><font face="宋体">上面的例子采用了注解来取得一个datasource的引用，另外一种方式就是使用</font></span><span style="font-style: italic; font-size: 10.5pt; font-family: 'Times New Roman';">DatabaseUnitils.getDataSource()</span><span style="font-size: 10.5pt; font-family: 'Times New Roman';">&nbsp;<font face="宋体">方法来取得datasource。</font></span><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><o:p></o:p></span></p>
<p class="0" style="text-align: justify;"><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><o:p></o:p></span></p>
<p class="0" style="text-align: justify;"><span style="font-style: italic; font-size: 14pt; font-family: 'Times New Roman';"><font face="宋体">事务</font></span><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><o:p></o:p></span></p>
<p class="0" style="text-align: justify;"><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><font face="宋体">出于不同的原因，我们的测试都是运行在一个事务中的，其中最重要的原因如下：</font></span><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><o:p></o:p></span></p>
<p class="0" style="margin-left: 21pt; text-indent: -21pt; text-align: justify;"><span style="font-size: 10.5pt; font-family: 'Wingdings';">l&nbsp;</span><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><font face="宋体">数据库的很多action都是在事务正常提交后才做，如</font></span><span style="font-style: italic; font-size: 10.5pt; font-family: 'Times New Roman';">SELECT&nbsp;FOR&nbsp;UPDATE</span><span style="font-size: 10.5pt; font-family: 'Times New Roman';">&nbsp;<font face="宋体">和触发器</font></span><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><o:p></o:p></span></p>
<p class="0" style="margin-left: 21pt; text-indent: -21pt; text-align: justify;"><span style="font-size: 10.5pt; font-family: 'Wingdings';">l&nbsp;</span><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><font face="宋体">许多项目在测试数据的时候都会填写一些测试数据，每个测试运行都会修改或者更新了数据，当下一个测试运行的时候，都需要将数据回复到原有的状态。</font></span><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><o:p></o:p></span></p>
<p class="0" style="margin-left: 21pt; text-indent: -21pt; text-align: justify;"><span style="font-size: 10.5pt; font-family: 'Wingdings';">l&nbsp;</span><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><font face="宋体">如果使用的是hibernate或者JPA的时候，都需要每个测试都运行在事务中，保证系统的正常工作。</font></span><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><o:p></o:p></span></p>
<p class="0" style="text-align: justify;"><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><o:p></o:p></span></p>
<p class="0" style="text-align: justify;"><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><font face="宋体">缺省情况下，事务管理是disabled的，事务的默认行为我们可以通过属性文件的配置加以改变：</font></span><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><o:p></o:p></span></p>
<p class="0" style="margin-top: 5pt; text-align: justify;"><span style="font-size: 10.5pt; font-family: 'Times New Roman';">DatabaseModule.Transactional.value.default=commit&nbsp;</span><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><o:p></o:p></span></p>
<p class="0" style="text-align: justify;"><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><font face="宋体">采用这个设置，每个的测试都将执行commit，其他的属性值还有</font></span><span style="font-style: italic; font-size: 10.5pt; font-family: 'Times New Roman';">rollback</span><span style="font-size: 10.5pt; font-family: 'Times New Roman';">&nbsp;<font face="宋体">和</font></span><span style="font-style: italic; font-size: 10.5pt; font-family: 'Times New Roman';">disabled</span><span style="font-size: 10.5pt; font-family: 'Times New Roman';">&nbsp;</span><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><o:p></o:p></span></p>
<p class="0" style="text-align: justify;"><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><o:p></o:p></span></p>
<p class="0" style="text-align: justify;"><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><font face="宋体">我们也可以通过在测试类上使用注解</font></span><span style="font-style: italic; font-size: 10.5pt; font-family: 'Times New Roman';">@Transactional</span><span style="font-size: 10.5pt; font-family: 'Times New Roman';">&nbsp;<font face="宋体">来改变默认的事务设置，如：</font></span><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><o:p></o:p></span></p>
<p class="0" style="margin-top: 5pt; text-align: justify;"><span style="font-size: 10.5pt; font-family: 'Times New Roman';">@Transactional(TransactionMode.ROLLBACK)&nbsp;</span><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><o:p></o:p></span></p>
<p class="0" style="margin-top: 5pt; text-align: justify;"><span style="font-size: 10.5pt; font-family: 'Times New Roman';">public&nbsp;class&nbsp;UserDaoTest&nbsp;extends&nbsp;UnitilsJUnit4&nbsp;{&nbsp;</span><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><o:p></o:p></span></p>
<p class="0" style="text-align: justify;"><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><font face="宋体">通过这种class上注解的事务管理，可以让每个测试都确保回滚，</font></span><span style="font-style: italic; font-size: 10.5pt; font-family: 'Times New Roman';">@Transactional</span><span style="font-size: 10.5pt; font-family: 'Times New Roman';">&nbsp;<font face="宋体">注解还可以继承的，因此我们可以将其放在父类中，而不必每个子类都进行声明。</font></span><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><o:p></o:p></span></p>
<p class="0" style="text-align: justify;"><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><o:p></o:p></span></p>
<p class="0" style="text-align: justify;"><span style="font-size: 10.5pt; font-family: 'Times New Roman';">.........</span><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><o:p></o:p></span></p>
<p class="0"><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><font face="宋体">如果你使用Unitils的spring支持（见使用spring进行测试）你如果配置了PlatformTransactionManager&nbsp;的bean，那么unitils将会使用这个事务管理。</font></span></p>
<img src ="http://www.blogjava.net/wangzhouyu/aggbug/224169.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/wangzhouyu/" target="_blank">小小~咖啡豆</a> 2008-08-25 15:11 <a href="http://www.blogjava.net/wangzhouyu/archive/2008/08/25/224169.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Unitils开发指南（二）</title><link>http://www.blogjava.net/wangzhouyu/archive/2008/04/07/191137.html</link><dc:creator>小小~咖啡豆</dc:creator><author>小小~咖啡豆</author><pubDate>Sun, 06 Apr 2008 16:45:00 GMT</pubDate><guid>http://www.blogjava.net/wangzhouyu/archive/2008/04/07/191137.html</guid><wfw:comment>http://www.blogjava.net/wangzhouyu/comments/191137.html</wfw:comment><comments>http://www.blogjava.net/wangzhouyu/archive/2008/04/07/191137.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.blogjava.net/wangzhouyu/comments/commentRss/191137.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/wangzhouyu/services/trackbacks/191137.html</trackback:ping><description><![CDATA[<h4><strong>Unitils模块</strong></h4>
<p><em>配置</em></p>
<p>和大多数的项目一样，unitils也需要一些配置，默认情况下有3个配置，每个配置都覆写前一个的配置</p>
<ol>
    <li>unitils-default.properties 默认的配置，在unitils发行包中。</li>
    <li>unitils.properties 可包含项目的全部配置</li>
    <li>unitils-local.properties 可以包含用户特定配置</li>
</ol>
<p>第一个配置文件unitils-default.properties，它包含了缺省值并被包含在unitils的发行包中。我们没有必要对这个文件进行修改，但它可以用来作参考。</p>
<p>第二个配置文件unitils.properties，它是我们需要进行配置的文件，并且能覆写缺省的配置。举个例子，如果你的项目使用的是oracle数据库，你可以创建一个unitils.properties文件并覆写相应的driver class和database url。</p>
<pre>database.driverClassName=oracle.jdbc.driver.OracleDriver
database.url=jdbc:oracle:thin:@yourmachine:1521:YOUR_DB</pre>
<p>这个文件并不是必须的，但是一旦你创建了一个，你就需要将该文件放置在项目的classpath下</p>
<p>最后一个文件，unitils-local.properties是可选的配置文件，它可以覆写项目的配置，用来定义开发者的具体设置，举个例子来说，如果每个开发者都使用自己的数据库schema，你就可以创建一个unitils-local.properties为每个用户配置自己的数据库账号、密码和schema。</p>
<pre>database.userName=john
database.password=secret
database.schemaNames=test_john</pre>
<p>每个unitils-local.properties文件应该放置在对应的用户文件夹中（<em>System.getProperty("user.home")</em>）。</p>
<p>本地文件名unitils-local.properties也可以通过配置文件定义，在unitils.properties覆写<em>unitils.configuration.localFileName</em>就可以。</p>
<pre>unitils.configuration.localFileName=projectTwo-local.properties</pre>
<p>&nbsp;</p>
<p><em>启用你的unitils</em></p>
<p>unitils的功能是依赖于基础的测试框架，要使用unitils的功能，就必须先enable他们，这样做的目的也是为了容易扩展。目前支持的框架有：</p>
<ol>
    <li>JUnit3 ：org.unitils.UnitilsJUnit3</li>
    <li>JUnit4 ：org.unitils.UnitilsJUnit4</li>
    <li>TestNG：org.unitils.UnitilsTestNG</li>
</ol>
<p>举个例子，如果使用JUnit3，你要使用unitils</p>
<pre><span style="color: #0000ff">import</span> org.unitils.UnitilsJUnit3;
<span style="color: #0000ff">public</span> <span style="color: #0000ff">class</span> MyTest <span style="color: #0000ff">extends</span> UnitilsJUnit3 {
}</pre>
<p>通常你将创建你自己的包含一些公共行为的测试基类，如dataSource的注入，你可以让这个基类继承unitils测试类。</p>
<p>当你使用的是JUnit4的话，你也可是使用<em>@RunWith</em>来代替继承unitils测试类</p>
<pre><span style="color: #0000ff">import</span> org.junit.runner.RunWith;
<span style="color: #0000ff">import</span> org.unitils.UnitilsJUnit4TestClassRunner;
@RunWith(UnitilsJUnit4TestClassRunner.<span style="color: #0000ff">class</span>)
<span style="color: #0000ff">public</span> <span style="color: #0000ff">class</span> MyTest {
}</pre>
<p>&nbsp;</p>
<p><em>模块系统</em></p>
<p>在开始举例之前，让我们先了解一下unitils概念。</p>
<p>unitils的结构被设计成了十分容易扩展，每个模块提供了一种服务，当执行Test的时候通过TestListener调用相应的服务。</p>
<p><a href="http://www.blogjava.net/images/blogjava_net/wangzhouyu/WindowsLiveWriter/Unitils_12D11/image_2.png"><img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="228" alt="image" src="http://www.blogjava.net/images/blogjava_net/wangzhouyu/WindowsLiveWriter/Unitils_12D11/image_thumb.png" width="466" border="0" /></a> </p>
<p>这种设计采用了一个统一的方式提供服务，如果你需要加入其他的服务，无需去改编测试基类（UnitilsJUnit4这些类）。要加入新的服务只需要添加一个新的模块并在unitls配置文件中登记这个模块。</p>
<p>目前unitils中所有有效的模块如下：</p>
<ol>
    <li><em>DatabaseModule</em> 数据库单元测试的维护和连接池。</li>
    <li><em>DbUnitModule</em> 使用DBUnit来管理测试数据。</li>
    <li><em>hibernatemodule</em> 支持Hibernate的配置和自动数据库映射检查。</li>
    <li><em>EasyMockModule</em> 支持创建mock和宽松的反射参数匹配。</li>
    <li><em>InjectModule</em> 支持在一个对象中注入另一个对象。</li>
    <li><em>SpringModule</em> 支持加载spring的上下文配置，并检索和Spring Bean注入。</li>
</ol>
<img src ="http://www.blogjava.net/wangzhouyu/aggbug/191137.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/wangzhouyu/" target="_blank">小小~咖啡豆</a> 2008-04-07 00:45 <a href="http://www.blogjava.net/wangzhouyu/archive/2008/04/07/191137.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Unitils开发指南（一）</title><link>http://www.blogjava.net/wangzhouyu/archive/2008/04/05/190908.html</link><dc:creator>小小~咖啡豆</dc:creator><author>小小~咖啡豆</author><pubDate>Sat, 05 Apr 2008 06:23:00 GMT</pubDate><guid>http://www.blogjava.net/wangzhouyu/archive/2008/04/05/190908.html</guid><wfw:comment>http://www.blogjava.net/wangzhouyu/comments/190908.html</wfw:comment><comments>http://www.blogjava.net/wangzhouyu/archive/2008/04/05/190908.html#Feedback</comments><slash:comments>5</slash:comments><wfw:commentRss>http://www.blogjava.net/wangzhouyu/comments/commentRss/190908.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/wangzhouyu/services/trackbacks/190908.html</trackback:ping><description><![CDATA[<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 单元测试应该是简单和直观的，而现实中的项目大多都是采用多层方式的，如EJB和hibernate的数据驱动层的中间件技术。  <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; unitils来源于一个尝试，就是希望能以更务实的方式来看待单元测试......  <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 这个指南会告诉你，什么项目可以使用unitils。 并在这个<a href="http://209.85.135.104/translate_c?hl=zh-CN&amp;langpair=en%7Czh-CN&amp;u=http://www.unitils.org/guidelines.html">指导方针页</a> 中你可以了解到测试的准侧和它的特点。如果您想了解如何可以配置unitils ，并得以迅速地启动，请查看<a href="http://209.85.135.104/translate_c?hl=zh-CN&amp;langpair=en%7Czh-CN&amp;u=http://www.unitils.org/cookbook.html">cookbook</a> 。  <ul> <li>unitils的断言  <li>unitils的模块  <li>数据库的测试  <li>数据库的自动测试  <li>hibernate的测试  <li>jpa的测试  <li>spring的测试  <li>mock object的测试  <li>今后的方向</li></ul> <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <strong>unitils的断言</strong></p> <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 在开始这个指南之前我们先说明一下独立于unitils核心模块的断言。在下面的例子中，不需要进行配置，将unitils的jar包和依赖包放在你的classpath下，就可以进行测试了。</p> <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 通过反射进行断言</p> <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 一个典型的单元测试包含了结果值和期望值的比较，unitils提供了断言的方法以帮助你进行该操作，让我们看看实例2中对有着id、first name、last name属性的User类的2个实例的比较</p><pre><span style="color: #0000ff">public</span> <span style="color: #0000ff">class</span> User {
    <span style="color: #0000ff">private</span> <span style="color: #0000ff">long</span> id;
    <span style="color: #0000ff">private</span> String first;
    <span style="color: #0000ff">private</span> String last;

    <span style="color: #0000ff">public</span> User(<span style="color: #0000ff">long</span> id, String first, String last) {
        <span style="color: #0000ff">this</span>.id = id;
        <span style="color: #0000ff">this</span>.first = first;
        <span style="color: #0000ff">this</span>.last = last;
    }
}

User user1 = <span style="color: #0000ff">new</span> User(1, "<span style="color: #8b0000">John</span>", "<span style="color: #8b0000">Doe</span>");
User user2 = <span style="color: #0000ff">new</span> User(1, "<span style="color: #8b0000">John</span>", "<span style="color: #8b0000">Doe</span>");
assertEquals(user1, user2);</pre><pre>    你期望这个断言是成功的，因为这两个实例含有相同的属性，但是运行的结果并非如此，应为User类并没有覆写<br>equals()方法，所以assertEquals是对两个实例是否相等进行判断（user1 == user2）结果导致了比较的失败。</pre><pre>    假设你像如下代码一样实现了equals方法</pre><pre><span style="color: #0000ff">public</span> <span style="color: #0000ff">boolean</span> equals(Object <span style="color: #0000ff">object</span>) {
    <span style="color: #0000ff">if</span> (<span style="color: #0000ff">object</span> <span style="color: #0000ff">instanceof</span> User) {
        <span style="color: #0000ff">return</span> id == ((User) <span style="color: #0000ff">object</span>).id;
    }
    <span style="color: #0000ff">return</span> <span style="color: #0000ff">false</span>;
}</pre>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 这在你的程序逻辑中是一个合乎逻辑的实现，当两个User实例拥有相同的id的时候，那么这两个实例就是相等的。然而这种方式在你的单元测试中并不合适，并不能通过id的相同来认为两个user是相同的。</p><pre>User user1 = <span style="color: #0000ff">new</span> User(1, "<span style="color: #8b0000">John</span>", "<span style="color: #8b0000">Doe</span>");
User user2 = <span style="color: #0000ff">new</span> User(1, "<span style="color: #8b0000">Jane</span>", "<span style="color: #8b0000">Smith</span>");
assertEquals(user1, user2);</pre>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 这个断言将会成功，但这并不是你所期望的，因此不要使用assertEquals来对两个对象进行判定是否相等（外覆类和java.lang.String类除外）。要想断言他们相等，一种方法就是断言每个属性相等。</p><pre>User user1 = <span style="color: #0000ff">new</span> User(1, "<span style="color: #8b0000">John</span>", "<span style="color: #8b0000">Doe</span>");
User user2 = <span style="color: #0000ff">new</span> User(1, "<span style="color: #8b0000">John</span>", "<span style="color: #8b0000">Doe</span>");
assertEquals(user1.getId(), user2.getId());
assertEquals(user1.getFirst(), user2.getFirst());
assertEquals(user1.getLast(), user2.getLast());</pre>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; unitils提供了一些方法来帮助你执行断言更加的简单，通过反射，使用<em>ReflectionAssert.assertRefEquals</em>上面的代码重写如下：</p><pre>User user1 = <span style="color: #0000ff">new</span> User(1, "<span style="color: #8b0000">John</span>", "<span style="color: #8b0000">Doe</span>");
User user2 = <span style="color: #0000ff">new</span> User(1, "<span style="color: #8b0000">John</span>", "<span style="color: #8b0000">Doe</span>");
assertRefEquals(user1, user2);</pre><pre>   这个断言将通过反射对两个实例中的每个属性都进行比较，先是id、然后是first name、最后是last name。</pre><pre>   如果一个属性本身也是一个对象，那么将会使用反射进行递归比较，这同样适合与集合、map、和数组之间的比较，他们<br>的每个元素会通过反射进行比较。如果值是一个基本类型或者是一个外覆类，那么将会使用==进行值的比较，因此下面的断<br>言会取得成功</pre><pre>assertRefEquals(1, 1L); 

List&lt;Double&gt; myList = <span style="color: #0000ff">new</span> ArrayList&lt;Double&gt;();
myList.add(1.0);
myList.add(2.0);
assertRefEquals(Arrays.asList(1, 2), myList);</pre>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <strong>宽松的断言</strong></p>
<p><strong>&nbsp;&nbsp;&nbsp;&nbsp; </strong>出于可维护性，这一点是十分重要的，举例说明：如果你要计算一个帐户的余额，那你就没比较检查这个帐户的名称。他只会增加复杂性，使之更难理解。如果你想让你的测试代码更容易生存，更容易重构的话，那请确保你断言的范围。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <em>宽松的顺序</em></p>
<p><em>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </em>在比较集合和数组的时候你可能并不关心他们中元素的顺序，通过使用<i>ReflectionAssert.assertRefEquals</i>方法并配合<i>ReflectionComparatorMode.LENIENT_ORDER</i>参数将忽略元素的顺序。</p><pre>List&lt;Integer&gt; myList = Arrays.asList(3, 2, 1);
assertRefEquals(Arrays.asList(1, 2, 3), myList, LENIENT_ORDER);</pre><pre>   <em>无视默认</em></pre><pre><em>   </em>第二种的从宽方式是使用<i>ReflectionComparatorMode.IGNORE_DEFAULTS</i>模式，当这种模式被设置的时候,java<br>的默认值，如null、0、false将会不参与断言（忽略）。</pre><pre>   举个例子，如果你有一个User类，该类有着first name，last name，street等属性，但是你仅仅想对first name<br>和street进行检查而忽略其他的属性。</pre><pre>User actualUser   = <span style="color: #0000ff">new</span> User("<span style="color: #8b0000">John</span>", "<span style="color: #8b0000">Doe</span>", <span style="color: #0000ff">new</span> Address("<span style="color: #8b0000">First street</span>", "<span style="color: #8b0000">12</span>", "<span style="color: #8b0000">Brussels</span>"));
User expectedUser = <span style="color: #0000ff">new</span> User("<span style="color: #8b0000">John</span>",  <span style="color: #0000ff">null</span>, <span style="color: #0000ff">new</span> Address("<span style="color: #8b0000">First street</span>", <span style="color: #0000ff">null</span>,       <span style="color: #0000ff">null</span>));
assertRefEquals(expectedUser, actualUser, IGNORE_DEFAULTS);</pre>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 你所期望忽略的属性的对象必须放在断言左边，如果放在右边那么依然进行比较。</p><pre>assertRefEquals(<span style="color: #0000ff">null</span>, anyObject, IGNORE_DEFAULTS);  <span style="color: #008000">// Succeeds</span>
assertRefEquals(anyObject, <span style="color: #0000ff">null</span>, IGNORE_DEFAULTS);  <span style="color: #008000">// Fails</span></pre>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <em>宽松的日期</em></p>
<p><em>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </em>第三种从宽处理是<em>ReflectionComparatorMode.LENIENT_DATES，</em>当两个日期都是值，或者都是null的时候，实际的日期将会被忽略（即断言为相等）。</p><pre>Date actualDate =   <span style="color: #0000ff">new</span> Date(44444);
Date expectedDate = <span style="color: #0000ff">new</span> Date();
assertRefEquals(expectedDate, actualDate, LENIENT_DATES);</pre>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <em>assertLenEquals </em></p>
<p><em>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ReflectionAssert</em>还提供了一种断言，他提供宽松的顺序又提供无视的忽略。</p><pre>List&lt;Integer&gt; myList = Arrays.asList(3, 2, 1);
assertLenEquals(Arrays.asList(1, 2, 3), myList); 

assertLenEquals(<span style="color: #0000ff">null</span>, "<span style="color: #8b0000">any</span>");  <span style="color: #008000">// Succeeds</span>
assertLenEquals("<span style="color: #8b0000">any</span>", <span style="color: #0000ff">null</span>);  <span style="color: #008000">// Fails</span></pre>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <strong>属性断言</strong></p>
<p><em>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; assertLenEquals</em>和<i>assertRefEquals</i>都是比较对象，ReflectionAssert也提供方法对对象的属性进行比较。（依赖与ONGL）。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 一些属性比较的例子</p><pre>assertPropertyLenEquals("<span style="color: #8b0000">id</span>", 1, user);  //断言user的id属性的值是1 
assertPropertyLenEquals("<span style="color: #8b0000">address.street</span>", "<span style="color: #8b0000">First street</span>", user); //断言user的address的street属性</pre>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 在这个方式中你期望的值和判定的对象也可以使用集合</p><pre>assertPropertyLenEquals("<span style="color: #8b0000">id</span>", Arrays.asList(1, 2, 3), users);
assertPropertyLenEquals("<span style="color: #8b0000">address.street</span>", Arrays.asList("<span style="color: #8b0000">First street</span>", <br>                        "<span style="color: #8b0000">Second street</span>", "<span style="color: #8b0000">Third street</span>"), users);</pre><img src ="http://www.blogjava.net/wangzhouyu/aggbug/190908.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/wangzhouyu/" target="_blank">小小~咖啡豆</a> 2008-04-05 14:23 <a href="http://www.blogjava.net/wangzhouyu/archive/2008/04/05/190908.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>单元测试的十二信条</title><link>http://www.blogjava.net/wangzhouyu/archive/2007/04/30/114712.html</link><dc:creator>小小~咖啡豆</dc:creator><author>小小~咖啡豆</author><pubDate>Mon, 30 Apr 2007 01:59:00 GMT</pubDate><guid>http://www.blogjava.net/wangzhouyu/archive/2007/04/30/114712.html</guid><wfw:comment>http://www.blogjava.net/wangzhouyu/comments/114712.html</wfw:comment><comments>http://www.blogjava.net/wangzhouyu/archive/2007/04/30/114712.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/wangzhouyu/comments/commentRss/114712.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/wangzhouyu/services/trackbacks/114712.html</trackback:ping><description><![CDATA[
<blockquote>
<ol>
<li>写代码，就一定要写测试</li>
<li>不要受单元测试的教条所限</li>
<li>相信单元测试将会带来的成果</li>
<li>统一考虑编码和测试</li>
<li>测试比单元代码重要</li>
<li>测试的最佳时机是代码刚写完之时</li>
<li>测试不会白费</li>
<li>当天有瑕疵的测试也比后补的完美测试好</li>
<li>不好的测试也比没有测试强</li>
<li>测试有时可以验证意图</li>
<li>只有傻瓜不用工具</li>
<li>用好的去测试不好的</li>
</ol>
<p>引至：Info中文网站<a href="http://www.infoq.com/cn/news/2007/04/savoia-tao-of-testing">http://www.infoq.com/cn/news/2007/04/savoia-tao-of-testing</a></p>
</blockquote>
<img src ="http://www.blogjava.net/wangzhouyu/aggbug/114712.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/wangzhouyu/" target="_blank">小小~咖啡豆</a> 2007-04-30 09:59 <a href="http://www.blogjava.net/wangzhouyu/archive/2007/04/30/114712.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>