powermock eclipse 'no last call on a mock available'

come from: http://www.douban.com/note/164083610/

插件的测试使用的是swtbot,内置junit的插件。
而mock主要类似stub的工作模式,用来模拟在unit test过程中,需要使用但是有没有办法拿到的一些对象。
我主要研究了一下easymock和powermock。powermock基于easymock实现,主要对easymock无法实现的静态方法,内部类,构造类等等方法的补充和实现。

esaymock的官网为:http://www.easymock.org/
我使用的是当前最新版本3.0,从官网上可以下载到最新的源码、jar包和文档,文档有详细的教程,同时诸多网站上有中文版本,整体比较简单,所以不加赘述。
需要说明的是jar包的问题,easymock本身不依赖于junit,但是运行时大多数都是在做测试,所以easymock.jar和junit.jar可以保证没有编译错误,但是运行时依然不好用,原因是它通过修改jvm中类的字节码实现mock,因此它依赖cglib-nodeep-2.2.jar和javassist.jar包。网上可以找到,是Jboss等第三方写的对字节码操作的基本类库。
官网描述如下
              EasyMock only works with Java 1.5.0 and above.
              cglib (2.2) and Objenesis (1.2) must be in the classpath to perform class mocking


powermock基于easymock实现,主要对easymock不能实现的类和方法的支持。
官网为:http://code.google.com/p/powermock/
它对Junit和testNG都有支持,同时也可以基于Mockito而不基于easymock。因为我使用的是junit的测试方法,所以研究了一下关于基于easymock的实现。

首先jar包问题
powermock实现了通过maven做依赖管理,因此可以直接把官网上的maven的信息copy到你的maven配置文件中,就可以拿到想要的jar包。
如果不依赖maven的话,官网上有可以下载的整体的zip包,主要包括几项内容:
easymock及其依赖的cglib和javassist,junit包,objenesis包(用于实现实例化类...),powermock自己的jar包

需要说明的是,powermock对版本的控制很严格,比如我下载的1.49版本的powermock,依赖3.0版本的easymock,1.2版本的objenesis,还依赖4.8.2版本的junit。
版本依赖比较严格,尤其是junit的jar包,4.8.1都有可能会导致不好用。

关于使用,
使用powermock主要是对easymock的弥补,实现静态方法、内部类、构造方法的mock。因此使用的时候主要注意两点,其余都和easymock没有区别。
1,使用@RunWith(runner....)   2, 使用 @PrepareForTest(***.class)

接下来进入正题,关于插件和powermock的协作。

首先
插件一般是用junit plugin test和swtbot协作完成非图形化和图形化的测试。这两种方式都是通过插件提供给用户使用的,意味着,它会附加junit插件,也意味着,它也是和junit版本绑定的。
swtbot针对当前版本的eclipse提供的有
eclipse version   ,     junit version
3.5                              4.5
3.6\3.7                        4.81


然后powermock对junit版本依赖为:
powermock      junit           
1.49                 4.82
1.4                   4.81

从上述可以看出,我们只要使用3.6\3.7的eclipse安装swtbot插件,然后使用powermock的1.4版本就可以解决问题。
但是事实往往不是这样的。

假设我们已经完成上述版本的eclipse平台的搭建,那么,运行的时候就会有一个问题,
@RunWith()的参数,
swtbot的参数是@RunWith(SWTBotJunit4ClassRunner.class)
powermock的参数是@RunWith(PowerMockRunner.class)

解决这个问题,powermock提供了rule的方式调用,这是基于junit的rule实现的。
也就是不适用@RunWith(PowerMockRunner.class),而在类的开始声明一个变量替代runner方式运行。
    @Rule
    public PowerMockRule rule = new PowerMockRule();

OK,这个问题也解决了,正常可以运行了吧。

这么说可以说对,也可以说不对。因此这样的方式,在普通的java项目中,已经可以实现,rule替代runner的方式,按照rule方式完全可以正确的运行测试用例。这提供了便利,比如说对于spring来说,可以既使用自己的runner也可以使用powermock,这点在官网上有相应的链接。

但是这种方式对插件来说依然不好使。

现象:
在插件项目中,运行普通项目好使的powermock rule用例,会抛出异常,去掉依赖的junit4插件,添加需要的4.82版本的junit类路径,按照junit test方式运行,可以工作。但是添加swtbot的runner按照swtbot方式运行,不好使。
分析:因为我测试使用的是eclipse 3.5也就是使用的junit 插件中junit的版本为4.5,powermock的rule最少运行在powermock的1.4版本上,也就是要求junit最少为4.81。
另一点就代表了,swtbot对junit插件是强依赖,也就是必须加入这项插件依赖,不然就会抛出no runner的异常。

于是,我换了eclipse,3.6和3.7版本都测试了。


{
3.6现象:
使用powermock runner方式编写,junit test运行,正常工作。
使用powermock rule方式编写,junit test方式运行报java.lang.NoSuchMethodError: org.powermock.api.support.ClassLoaderUtil.loadClass(Ljava/lang/String;)Ljava/lang/Class异常。
()
而且无论我使用自己添加还是junit4插件中的juint 4.8.1,都会抛出这个异常。

3.7现象
使用powermock runner方式编写,junit test运行,正常工作。
使用powermock rule方式编写,junit test方式运行,正常工作。

使用powermock rule方式编写,swtbot test方式运行,抛出异常。

原因是什么?(我没有细致的去研究swtbot和powermock的源码,有些内容分析可能不正确)
我认为是junit版本的冲突,以及插件的类加载问题。


版本冲突可以解决。
类加载问题比较复杂,3.6一直抛出类加载异常,3.7则一直是assert异常。具体原因不详。
而插件运行状态的时候的运行时的classloader和load插件中的类的classloader是两个(这是一种原因)
}

上面测试出问题了,原因是powermock rule模式所依赖的几个jar包也是有版本问题的。



这是这两天的测试结果。


OK,继续说上述话题。
测试数据有误,懒得改上面,直接加在下面。


powermock rule方式

eclipse        swtbot_junit            powermock_junit     powermock 
3.5               4.5                               4.82                     1.49
添加powermock的jar包到编译路径和运行时,同时配置好swtbot所需的依赖插件,junit test方式run ,抛出异常_java.lang.IllegalStateException: no last call on a mock available
把plugin.xml中的junit4的插件删除,junit test方式run 好使
但是,按照swtbot test方式运行,抛出异常 java.lang.Exception: No runnable methods
不删除plugin.xml中的junit4的插件,抛出异常java.lang.NoClassDefFoundError: org/powermock/modules/junit4/rule/PowerMockRule
分析,因为swtbot_junit和powermock_junit版本不一致导致,插件会优先加载swtbot_junit,但是swtbot_junit的版本不足够满足powermock需求。另外,swtbot和powermock对junit版本有比较强的依赖。@RunWith属性似乎对于运行时的swtbot没有影响,因为无论有没有都会报NoClassDefFoundError异常。

powermock rule方式

eclipse        swtbot_junit  JDT_Junit           powermock_junit     powermock 
3.6               4.81                  4.82                 4.81                     1.47

添加powermock的jar包到编译路径和运行时,同时配置好swtbot所需的依赖插件,junit test方式run ,不删除junit4插件依赖,好使。删除也好使。

按照swtbot test方式运行,java.lang.ClassNotFoundException: org.easymock.internal.LastControl

我看了一下easymock中,有这个类,那就是加载类的问题了。

现在麻烦在于swtbot、JDT、powermock都有对Junit的依赖,首先是加载容器的问题,其次是加载顺序的问题。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值