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的依赖,首先是加载容器的问题,其次是加载顺序的问题。