谈Groovy为Java做单元测试

| |
[晴 2008/09/08 15:57 | by xeric ]
最近看到有人在Infoq写了用Jruby为Java写测试用例,
感觉不错,脚本语言的简便性得以充分发挥,于是不免手痒,尝试了一下,
Jruby虽好,却发现需要进行编译时出来诸多问题,比如java代码必须放入jruby的libpath下,
虽然不是什么大事,却无形中增加了推广难度,大家肯定会排斥做测试还需要这么麻烦的操作。
当然不是没有办法,不过似乎看上去很美的东西总是存在缺憾。
这个和Jruby不是Java原生支持的脚本有一定关系,于是想到了Groovy。
果然,尝试了一下Groovy后,发现其集成度远优于Jruby,
很简单的调用IDE中部署好的java类,无需任额外配置就可以run起来。
于是感觉找到了新路可走,深入挖掘,
单元测试最繁琐的事情当然属mock对象,一个代码中充斥了各种依赖的类,
这些类在正常的运行中又依赖于其他类和诸多环境变量和配置。
当然Groovy是个不错的语言,对于Junit的支持非常优秀,提供了MockFor和StubFor的方法来处理mock。
简单易懂,不过随着测试代码烦琐的深入,问题逐渐出现了。
我需要测试的一个业务类中,调用了一个读取配置的Util,
当然,除非我的运行环境全部run起来才有可能读取到这个配置,否则是读取不了的。
就是以为着我要mock这个读取配置的Util。
这个是个很典型的Groovy范例,我当时看了doc后是这样想的。
然而事实却远比我想象残酷,在我找遍了所有资料,尝试了n种做法后,
突然发现一个严重的问题,所有的例子里,你要mock的对象需要生效,比如是在groovy的脚本中才可以,
换句话说,我mock了一个util类,是的,我确实成功了,我在下面代码总这样使用

import groovy.mock.interceptor.MockFor
class JavaGroovyTest extends GroovyTestCase{
 void firstTest(){
   def mock = new MockFor(JavaUtil)
   mock.demand.returnValue(1..2){false}//before mock, this return true
   mock.use{
     println(JavaUtil.retrunValue())
   }
 }
}

如我所料的返回了false,然而当这个util被包含在一个java类写的业务逻辑总,严重问题出现了,
groovy的mock无法使作用域进入class。

//java class, this is java code!
public class JavaClass
{
   public boolean doReturnValue(){
       return JavaUtil.returnValue();
   }
}


import groovy.mock.interceptor.MockFor
class JavaGroovyTest extends GroovyTestCase{
 void firstTest(){
   def mock = new MockFor(JavaUtil)
   mock.demand.returnValue(1..2){false}//before mock, this return true
   mock.use{
     def jc = new JavaClass()
     println(jc.doReturnValue())
   }
 }
}

返回的值依旧是true,而且抛出一个异常:
junit.framework.AssertionFailedError: verify[0]: expected 1..2 call(s) to 'returnValue' but was called 0 time(s).
开始还没理解这个错误究竟怎么回事,后来发现,由于所调用的returnValue是在java的class中,
对于这个测试用例来说,根本就没有调到mock出来的returnValue方法,而这个方法要求至少被执行1-2次,
这个执行操作没有发生,因此就抛出了这个错。
如果mock根本就无法介入java的class,那么意味着使用Groovy的纯粹性大大下降,
我们写测试的话,必须把java和groovy混着写才行,我想没有一个公司的代码管理者希望看到这样的情况。
不知道有没有其他办法来解决这个问题,我暂时是没辙了,
感觉上想让脚本进入项目还有点时间。
Tags: ,
开发[DEV] | 评论(1) | 引用(0) | 阅读(395)
johnnyjian Homepage
2008/09/24 23:31
这是因为MockFor是通过MetaClass拦截了方法调用,而只有Groovy类才会通过MetaClass调用方法,Java类是直接调用方法的,也就是说Java写的方法调用无法被MockFor拦截。可以直接用Groovy的闭包mock方法(http://groovy.codehaus.org...),也可以用JMock或者EasyMock
分页: 1/1 第一页 [1] 最后页
发表评论
表情
emotemotemotemotemot
emotemotemotemotemot
emotemotemotemotemot
emotemotemotemotemot
emotemotemotemotemot
打开HTML
打开UBB
打开表情
隐藏
昵称   密码   游客无需密码
网址   电邮   [注册]
               

验证码 请输入左侧的字母,不区分大小写