﻿<?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-心有多大，舞台就有多大-随笔分类-grails</title><link>http://www.blogjava.net/yangpingyu/category/48541.html</link><description /><language>zh-cn</language><lastBuildDate>Sat, 14 May 2011 09:55:04 GMT</lastBuildDate><pubDate>Sat, 14 May 2011 09:55:04 GMT</pubDate><ttl>60</ttl><item><title>grails学习（二）grails单元测试</title><link>http://www.blogjava.net/yangpingyu/archive/2011/05/13/350200.html</link><dc:creator>yangpingyu</dc:creator><author>yangpingyu</author><pubDate>Fri, 13 May 2011 13:40:00 GMT</pubDate><guid>http://www.blogjava.net/yangpingyu/archive/2011/05/13/350200.html</guid><wfw:comment>http://www.blogjava.net/yangpingyu/comments/350200.html</wfw:comment><comments>http://www.blogjava.net/yangpingyu/archive/2011/05/13/350200.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/yangpingyu/comments/commentRss/350200.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/yangpingyu/services/trackbacks/350200.html</trackback:ping><description><![CDATA[以前我在小公司，完成项目功能是终极目标。开发人员很害怕需求变化，因为他们改怕了。那问题出在哪里呢？后来我仔细想想，是没有做测试造成。那开发人员为什么如此害怕需求变化，我举个例子，a服务给b服务和c服务调用，后来需求改变，导致a服务无法满足b服务，能完成自身的功能是天大的事，于是没有和别人沟通把a服务直接改了。项目上线，突然有一天客户打电话说你们网站这里出问题，那里出问题，以前都不会的啊。你们怎么弄的。于是根据页面错误信息，开发人员很快找到错误根源，原来a服务改动，导致b服务不正常。而d，e，f服务依赖于b，那么导致d，e，f相关功能都出错了。立马动手改，改完上线，能知道的问题都没了，哈哈，真高兴，可是不能高兴太早哇，也许还有潜在bug。<br />
<br />
软件的bug是无法避免，但是我们可以尽量减少bug，不断提升代码质量。刚我也说过，上述问题造成的原因是没有做测试。测试包括很多了，单元测试、集成测试和功能测试等等。既然测试如此重要，每完成一个类都能进行测试。<br />
<br />
以前也许你比较纠结，没有好的工具，现在java社区非常活跃，我们可以选择的太多太多了：junit4，jmock，mockito，easymock，TestNg等等。如果你用过grails，那么你更清楚，此类快速开发框架已经帮我们集成好了。使用起来非常简单。所以今天我主要讲述下grails的单元测试。<br />
<br />
假设需求：我们给每个用户分配工作，每个人都要完成两件事情，第一件事情：根据自己的用户名返回欢迎信息；第二件事情：根据自己的地址返回国家地区。<br />
<br />
详细设计<br />
<br />
用户信息类：<br />
<div style="background-color: #eeeeee; font-size: 13px; border: 1px solid #cccccc; padding: 4px 5px 4px 4px; width: 98%;"><span style="color: #0000ff;">package</span><span style="color: #000000;">&nbsp;com.test.domian<br />
<br />
</span><span style="color: #0000ff;">class</span><span style="color: #000000;">&nbsp;User&nbsp;{<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;id<br />
&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;name<br />
&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;address<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">static</span><span style="color: #000000;">&nbsp;constraints&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
}<br />
</span></div>
<br />
工作服务接口：<br />
<div style="background-color: #eeeeee; font-size: 13px; border: 1px solid #cccccc; padding: 4px 5px 4px 4px; width: 98%;"><span style="color: #0000ff;">package</span><span style="color: #000000;">&nbsp;com.test.services<br />
<br />
</span><span style="color: #0000ff;">class</span><span style="color: #000000;">&nbsp;WorkService&nbsp;{<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">/**</span><span style="color: #008000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;根据用户名返回欢迎字符<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span style="color: #808080;">@param</span><span style="color: #008000;">&nbsp;userName<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span style="color: #808080;">@return</span><span style="color: #008000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">*/</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;def&nbsp;processWorkOne(String&nbsp;userName)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">/**</span><span style="color: #008000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;根据地址返回地区<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span style="color: #808080;">@param</span><span style="color: #008000;">&nbsp;address<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span style="color: #808080;">@return</span><span style="color: #008000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">*/</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;def&nbsp;processWorkTwo(String&nbsp;address){<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
}</span></div>
<br />
用户工作服务：<br />
<div style="background-color: #eeeeee; font-size: 13px; border: 1px solid #cccccc; padding: 4px 5px 4px 4px; width: 98%;"><span style="color: #0000ff;">package</span><span style="color: #000000;">&nbsp;com.test.services<br />
<br />
</span><span style="color: #0000ff;">import</span><span style="color: #000000;">&nbsp;com.test.domian.User<br />
<br />
</span><span style="color: #0000ff;">class</span><span style="color: #000000;">&nbsp;UserService&nbsp;{<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;def&nbsp;workService<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;def&nbsp;doWork()&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;def&nbsp;userList&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;User.list()<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;userList.each&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;it.name&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;workService.processWorkOne(it.name)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;it.address&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;workService.processWorkTwo(it.address)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
}</span></div>
<br />
我们重点来看下测试类：<br />
<div style="background-color: #eeeeee; font-size: 13px; border: 1px solid #cccccc; padding: 4px 5px 4px 4px; width: 98%;"><span style="color: #0000ff;">package</span><span style="color: #000000;">&nbsp;com.test.services<br />
<br />
</span><span style="color: #0000ff;">import</span><span style="color: #000000;">&nbsp;grails.test.</span><span style="color: #000000;">*</span><span style="color: #000000;"><br />
<br />
</span><span style="color: #0000ff;">import</span><span style="color: #000000;">&nbsp;com.test.domian.User<br />
<br />
</span><span style="color: #0000ff;">class</span><span style="color: #000000;">&nbsp;UserServiceTests&nbsp;</span><span style="color: #0000ff;">extends</span><span style="color: #000000;">&nbsp;GrailsUnitTestCase&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">protected</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;setUp()&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">super</span><span style="color: #000000;">.setUp()<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">protected</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;tearDown()&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">super</span><span style="color: #000000;">.tearDown()<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;testDoWork()&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">构造数据，类似于数据库存在三条记录</span><span style="color: #008000;"><br />
</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;def&nbsp;user1&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;User(id:</span><span style="color: #000000;">1</span><span style="color: #000000;">,&nbsp;name:</span><span style="color: #000000;">"</span><span style="color: #000000;">lucy</span><span style="color: #000000;">"</span><span style="color: #000000;">,&nbsp;address:</span><span style="color: #000000;">"</span><span style="color: #000000;">hangzhou</span><span style="color: #000000;">"</span><span style="color: #000000;">)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;def&nbsp;user2&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;User(id:</span><span style="color: #000000;">2</span><span style="color: #000000;">,&nbsp;name:</span><span style="color: #000000;">"</span><span style="color: #000000;">lily</span><span style="color: #000000;">"</span><span style="color: #000000;">,&nbsp;address:</span><span style="color: #000000;">"</span><span style="color: #000000;">wenzhou</span><span style="color: #000000;">"</span><span style="color: #000000;">)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;def&nbsp;user3&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;User(id:</span><span style="color: #000000;">3</span><span style="color: #000000;">,&nbsp;name:</span><span style="color: #000000;">"</span><span style="color: #000000;">lilei</span><span style="color: #000000;">"</span><span style="color: #000000;">,&nbsp;address:</span><span style="color: #000000;">"</span><span style="color: #000000;">beijing</span><span style="color: #000000;">"</span><span style="color: #000000;">)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mockDomain&nbsp;User,&nbsp;[user1,&nbsp;user2,&nbsp;user3]<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">mock&nbsp;WorkService接口的processWorkOne方法和processWorkTwo方法</span><span style="color: #008000;"><br />
</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;def&nbsp;workControl&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;mockFor(WorkService)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;def&nbsp;userCount&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;User.count()<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">while</span><span style="color: #000000;">(userCount</span><span style="color: #000000;">--</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">&gt;</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">0</span><span style="color: #000000;">){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;workControl.demand.processWorkOne(</span><span style="color: #000000;">1</span><span style="color: #000000;">..</span><span style="color: #000000;">1</span><span style="color: #000000;">){String&nbsp;userName&nbsp;</span><span style="color: #000000;">-&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">hello&nbsp;world,&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">&lt;&lt;</span><span style="color: #000000;">&nbsp;userName<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;workControl.demand.processWorkTwo(</span><span style="color: #000000;">1</span><span style="color: #000000;">..</span><span style="color: #000000;">1</span><span style="color: #000000;">){String&nbsp;address&nbsp;</span><span style="color: #000000;">-&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">location&nbsp;in&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">&lt;&lt;</span><span style="color: #000000;">&nbsp;address<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;def&nbsp;workService&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;workControl.createMock()<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">把构造好的workservice传给userservice</span><span style="color: #008000;"><br />
</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;UserService&nbsp;userService&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;UserService()<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;userService.workService&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;workService<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;userService.doWork()<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;def&nbsp;user4&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;User.findById(</span><span style="color: #000000;">1</span><span style="color: #000000;">)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;assertEquals&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">hello&nbsp;world,&nbsp;lucy</span><span style="color: #000000;">"</span><span style="color: #000000;">,&nbsp;user4.name<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;assertEquals&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">location&nbsp;in&nbsp;hangzhou</span><span style="color: #000000;">"</span><span style="color: #000000;">,&nbsp;user4.address<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
}<br />
</span></div>
<br />
以下着重来具体说明：<br />
1、<span style="color: #000000;">mockDomain方法就是构造数据，包括domain类的动态方法都可以使用，比如：save（），list（），findby*（）等。代码中的User.count(); User.list();就是因为调用了mockDomain方法才可以正常使用。如果是集成测试的话，grails会帮我们构造好，可以直接使用。但这里是单元测试，所以需要自己mock。<br />
<br />
2、mockFor方法就是给WorkService构造一个对象，然后给</span><span style="color: #000000;">workControl对象的demand代理创建两个UserService中用的</span><span style="color: #000000;">processWorkOne和</span><span style="color: #000000;">processWorkTwo方法，代码中用到了1..1，表示mock对象只能调用这个方法一次，为什么要循环三次设置</span><span style="color: #000000;">processWorkOne和</span><span style="color: #000000;">processWorkTwo方法呢？因为我们在UserService是对三个对象分别进行调用处理这两件事情。也许你会想，干嘛不直接把1..3（最少调用一次，最多调用三次）。是的，我最开始也是这么来处理，可是单元测试就是同不过。<br />
如果把</span><span style="color: #000000;">UserService类中的</span><br />
<span style="color: #000000;">workControl.demand.processWorkOne(</span><span style="color: #000000;">1</span><span style="color: #000000;">..</span><span style="color: #000000;">1</span><span style="color: #000000;">){String&nbsp;userName&nbsp;</span><span style="color: #000000;">-&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">hello&nbsp;world,&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">&lt;&lt;</span><span style="color: #000000;">&nbsp;userName<br />
&nbsp;}</span><br />
改成<br />
<span style="color: #000000;">workControl.demand.processWorkOne(</span><span style="color: #000000;">1</span><span style="color: #000000;">..</span><span style="color: #000000;">3</span><span style="color: #000000;">){String&nbsp;userName&nbsp;</span><span style="color: #000000;">-&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">hello&nbsp;world,&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">&lt;&lt;</span><span style="color: #000000;">&nbsp;userName<br />
&nbsp;}</span><br />
然后把<span style="color: #000000;">UserServiceTests类中的：</span><br />
<span style="color: #000000;">userList.each&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;it.name&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;workService.processWorkOne(it.name)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;it.address&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;workService.processWorkTwo(it.address)<br />
}<br />
改成<br />
</span><span style="color: #000000;">userList.each&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;it.name&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;workService.processWorkOne(it.name)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: #000000;">it.name&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;workService.processWorkOne(it.name)</span><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color: #000000;">it.name&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;workService.processWorkOne(it.name)</span><br />
<span style="color: #000000;">
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;it.address&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;workService.processWorkTwo(it.address)<br />
}</span><br />
单元测试可以通过，但是改成这样<br />
<span style="color: #000000;">userList.each&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;it.name&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;workService.processWorkOne(it.name)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: #000000;">it.name&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;workService.processWorkOne(it.name)</span><br />
<span style="color: #000000;">
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;it.address&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;workService.processWorkTwo(it.address)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: #000000;">it.name&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;workService.processWorkOne(it.name)</span><br />
<span style="color: #000000;">
}</span><br />
单元测试通不过。<br />
以上就是表明1..3的含义：这个方法要连续被调用至少一次，至多三次。<br />
但是有的人说我在UserService中就要这么写<br />
<span style="color: #000000;">userList.each&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;it.name&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;workService.processWorkOne(it.name)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: #000000;">it.name&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;workService.processWorkOne(it.name)</span><br />
<span style="color: #000000;">
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;it.address&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;workService.processWorkTwo(it.address)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: #000000;">it.name&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;workService.processWorkOne(it.name)</span><br />
<span style="color: #000000;">
}<br />
那我要怎么改单元测试才能通过？<br />
我们把</span><span style="color: #000000;">UserServiceTests的demand这段代码<br />
</span><span style="color: #000000;">workControl.demand.processWorkOne(</span><span style="color: #000000;">1</span><span style="color: #000000;">..</span><span style="color: #000000;">1</span><span style="color: #000000;">){String&nbsp;userName&nbsp;</span><span style="color: #000000;">-&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">hello&nbsp;world,&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">&lt;&lt;</span><span style="color: #000000;">&nbsp;userName<br />
}<br />
workControl.demand.processWorkTwo(</span><span style="color: #000000;">1</span><span style="color: #000000;">..</span><span style="color: #000000;">1</span><span style="color: #000000;">){String&nbsp;address&nbsp;</span><span style="color: #000000;">-&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">location&nbsp;in&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">&lt;&lt;</span><span style="color: #000000;">&nbsp;address<br />
}</span><br />
<span style="color: #000000;">改成<br />
</span><span style="color: #000000;">workControl.demand.processWorkOne(</span><span style="color: #000000;">1</span><span style="color: #000000;">..</span><span style="color: #000000;">2</span><span style="color: #000000;">){String&nbsp;userName&nbsp;</span><span style="color: #000000;">-&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">hello&nbsp;world,&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">&lt;&lt;</span><span style="color: #000000;">&nbsp;userName<br />
}<br />
workControl.demand.processWorkTwo(</span><span style="color: #000000;">1</span><span style="color: #000000;">..</span><span style="color: #000000;">1</span><span style="color: #000000;">){String&nbsp;address&nbsp;</span><span style="color: #000000;">-&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">location&nbsp;in&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">&lt;&lt;</span><span style="color: #000000;">&nbsp;address<br />
&nbsp;}</span><br />
<span style="color: #000000;">workControl.demand.</span><span style="color: #000000;">processWorkOne</span><span style="color: #000000;">(</span><span style="color: #000000;">1</span><span style="color: #000000;">..</span><span style="color: #000000;">1</span><span style="color: #000000;">){String&nbsp;address&nbsp;</span><span style="color: #000000;">-&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">location&nbsp;in&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">&lt;&lt;</span><span style="color: #000000;">&nbsp;address<br />
&nbsp;}<br />
这样就通过了。<br />
以上就是说明构造出来的函数只能按照构造的顺序调用。今天就是因为这个花了我好长时间啊，希望我理解是正确的。如有不对，请留言纠正。</span><span style="color: #000000;"><br />
<br />
<br />
</span>
<img src ="http://www.blogjava.net/yangpingyu/aggbug/350200.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/yangpingyu/" target="_blank">yangpingyu</a> 2011-05-13 21:40 <a href="http://www.blogjava.net/yangpingyu/archive/2011/05/13/350200.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>grails学习（一）Grails工程与maven集成</title><link>http://www.blogjava.net/yangpingyu/archive/2011/05/10/349898.html</link><dc:creator>yangpingyu</dc:creator><author>yangpingyu</author><pubDate>Tue, 10 May 2011 02:34:00 GMT</pubDate><guid>http://www.blogjava.net/yangpingyu/archive/2011/05/10/349898.html</guid><wfw:comment>http://www.blogjava.net/yangpingyu/comments/349898.html</wfw:comment><comments>http://www.blogjava.net/yangpingyu/archive/2011/05/10/349898.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/yangpingyu/comments/commentRss/349898.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/yangpingyu/services/trackbacks/349898.html</trackback:ping><description><![CDATA[<span style="font-family: 黑体;"><span style="font-size: 12pt;">&nbsp;
<p><span style="font-family: 黑体; font-size: 12pt;">Grails</span><span style="font-family: 黑体; font-size: 12pt;">工程与maven集成</span></p>
<p><span style="font-family: 黑体; font-size: 12pt;">Grails</span><span style="font-family: 黑体; font-size: 12pt;">其实也有自己的一些项目管理命令，如：grails package，grails test-app，grails war等。但是公司现在基本上都是用maven来管理项目，所以从管理上进行统一的目的，我们也让grails工程由maven来管理。</span></p>
<p><span style="font-family: 黑体; font-size: 12pt;">Grails</span><span style="font-family: 黑体; font-size: 12pt;">与maven集成是靠maven插件机制。</span></p>
<p><span style="font-family: 黑体; font-size: 12pt;">接下来描述下集成的步骤：</span></p>
<p style="text-indent: -18pt; margin-left: 18pt;" class="MsoListParagraph"><span style="font-family: 黑体; font-size: 12pt;">1、</span><span style="font-family: 黑体; font-size: 12pt;">在$home/.m2/settings.xml中配置plugin group</span></p>
<p style="text-align: left;" class="MsoNormal" align="left"><span style="font-family: 黑体; font-size: 12pt;">&lt;settings&gt;</span></p>
<p style="text-align: left;" class="MsoNormal" align="left"><span style="font-family: 黑体; font-size: 12pt;">&nbsp;</span><span style="font-family: 黑体; font-size: 12pt;">&#8230;</span></p>
<p style="text-align: left;" class="MsoNormal" align="left"><span style="font-family: 黑体; font-size: 12pt;">&nbsp;&lt;pluginGroups&gt;</span></p>
<p style="text-align: left;" class="MsoNormal" align="left"><span style="font-family: 黑体; font-size: 12pt;">&nbsp;&nbsp;&nbsp; &lt;pluginGroup&gt;org.grails&lt;/pluginGroup&gt;</span></p>
<p style="text-align: left;" class="MsoNormal" align="left"><span style="font-family: 黑体; font-size: 12pt;">&nbsp;&lt;/pluginGroups&gt;</span></p>
<p style="text-align: left;" class="MsoNormal" align="left"><span style="font-family: 黑体; font-size: 12pt;">&lt;/settings&gt;</span></p>
<p><span style="font-family: 黑体; font-size: 12pt;">没有配置之前，要运行grails：help命令要这样写：mvn org.grails:help，有了配置之后我们就可以这么写：mvn grails:help。</span></p>
<p><span style="font-family: 黑体; font-size: 12pt;">2</span><span style="font-family: 黑体; font-size: 12pt;">、我们创建一个maven管理的grails工程</span></p>
<pre><span style="font-family: 黑体;">Mvn org.apache.maven.plugins:maven-archetype-plugin:2.0-alpha-4:generate</span></pre>
<pre><span style="font-family: 黑体;"> &nbsp;&nbsp;&nbsp;-DarchetypeGroupId=org.grails </span></pre>
<pre><span style="font-family: 黑体;">&nbsp;&nbsp;&nbsp;&nbsp;-DarchetypeArtifactId=grails-maven-archetype </span></pre>
<pre><span style="font-family: 黑体;">&nbsp;&nbsp;&nbsp;&nbsp;-DarchetypeVersion=1.2.0 </span></pre>
<pre style="text-indent: 23.25pt;"><span style="font-family: 黑体;">-DgroupId=example -DartifactId=my-app</span></pre>
<pre><span style="font-family: 黑体;">grails-maven-archetype</span><span style="font-family: 黑体;">这里用的是1.2.0版本，好像maven3集成的版本比这个要新。</span></pre>
<pre>&nbsp;</pre>
<pre><span style="font-family: 黑体;">3</span><span style="font-family: 黑体;">、进入my-app当前目录，运行mvn initialize</span></pre>
<pre><span style="font-family: 黑体;">在运行过程中可能会出现如下问题：</span></pre>
<pre><span style="font-family: 黑体;">Resolving plugin JAR dependencies </span><span style="font-family: 黑体;">&#8230;</span></pre>
<pre><span style="font-family: 黑体;">:: problems summary ::</span></pre>
<pre><span style="font-family: 黑体;">:::: WARNINGS</span></pre>
<pre><span style="font-family: 黑体;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; module not found: org.hibernate#hibernate-core;3.3.1.GA</span></pre>
<pre><span style="font-family: 黑体;">那么你在application.properties文件中添加plugins.hibernate=1.3.2</span></pre>
<pre><span style="font-family: 黑体;">plugins.tomcat=1.3.2</span><span style="font-family: 黑体;">两个插件。最后运行mvn compile重新编译工程。</span></pre>
<pre>&nbsp;</pre>
<pre><span style="font-family: 黑体;">4</span><span style="font-family: 黑体;">、我们是用springsource tool suite开发，导入工程。项目中需要对excel操作，我们采用jxl.jar开源包。在pom文件中配置如下内容：</span></pre>
<p style="text-align: left;" class="MsoNormal" align="left"><span style="font-family: 黑体; font-size: 12pt;">&lt;dependency&gt;</span></p>
<p style="text-align: left;" class="MsoNormal" align="left"><span style="font-family: 黑体; font-size: 12pt;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;groupId&gt;<u>jxl</u>&lt;/groupId&gt;</span></p>
<p style="text-align: left;" class="MsoNormal" align="left"><span style="font-family: 黑体; font-size: 12pt;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;artifactId&gt;<u>jxl</u>&lt;/artifactId&gt;</span></p>
<p style="text-align: left;" class="MsoNormal" align="left"><span style="font-family: 黑体; font-size: 12pt;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;version&gt;2.4.2&lt;/version&gt;</span></p>
<pre style="text-indent: 21pt;"><span style="font-family: 黑体;">&lt;/dependency&gt;</span></pre>
<pre style="text-indent: 21pt;"><span style="font-family: 黑体;">重新编译下工程，但是引用jxl包中类的文件还是报错，说找不到类。这怎么回事呢？我也很纳闷，一般maven工程都是这样就可以。</span></pre>
<pre style="text-indent: 21pt;">&nbsp;</pre>
<pre style="text-indent: 21pt;"><span style="font-family: 黑体;">后来在官方文档上看到一句话：pom=true。只要把这句话加到conf/BuildConfig.groovy文件中的grails.project.dependency.resolution方法中。如图：</span></pre>
<pre style="text-indent: 21pt;">&nbsp;<img alt="" src="http://www.blogjava.net/images/blogjava_net/yangpingyu/111111111111.jpg" border="0" /></pre>
<pre><span style="font-family: 黑体;">重新编译，但是还是报错。Ide还是无法引用jxl包中的类。后来发现在grails tools中找到了一个命令。</span></pre>
<pre style="text-indent: 21pt;">&nbsp;<img alt="" src="http://www.blogjava.net/images/blogjava_net/yangpingyu/222222222222.jpg" border="0" /></pre>
<pre style="text-indent: 21pt;"><span style="font-family: 黑体;">执行过后，已经加入到了grails dependencies中。</span></pre>
<pre style="text-indent: 21pt;">&nbsp;</pre>
<pre style="text-indent: 21pt;"><span style="font-family: 黑体;">为什么会这样呢，是因为有两套机制造成的。</span></pre>
<pre style="text-indent: 21pt;"><span style="font-family: 黑体;">第一套机制：maven自身管理项目的机制。</span></pre>
<pre style="text-indent: 21pt;"><span style="font-family: 黑体;">第二套机制：grails也有自己的一套管理机制。</span></pre>
<pre style="text-indent: 21pt;">&nbsp;</pre>
<pre style="text-indent: -21pt; margin-left: 21pt;"><span style="font-family: Wingdings;">l&nbsp;</span><span style="font-family: 黑体;">在绝大多数情况下maven通过grails的集成插件可以对工程进行打包，部署，运行测试等管理。</span></pre>
<pre style="text-indent: -21pt; margin-left: 21pt;"><span style="font-family: Wingdings;">l&nbsp;</span><span style="font-family: 黑体;">Grails</span><span style="font-family: 黑体;">可以通过自己的grails war等命令进行打包，部署，运行测试等管理。</span></pre>
<pre style="text-indent: -21pt; margin-left: 21pt;"><span style="font-family: Wingdings;">l&nbsp;</span><span style="font-family: 黑体;">Grails</span><span style="font-family: 黑体;">也可以通过配置pom=true让grails那套管理机制用pom中的配置，不使用自己的管理机制。此时你就不用在conf/BuildConfig.groovy中管理依赖和资源库等配置。</span></pre>
<pre>&nbsp;</pre>
</span></span>
<img src ="http://www.blogjava.net/yangpingyu/aggbug/349898.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/yangpingyu/" target="_blank">yangpingyu</a> 2011-05-10 10:34 <a href="http://www.blogjava.net/yangpingyu/archive/2011/05/10/349898.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>