在Android单元测试中,Mockito和PowerMock这两种工具都可以用一个虚拟的对象来替换那些外部的、不容易构造的对象,解决Units之间由于耦合而难于被测试的问题。
两者的不同点在于Mockito对于大多数的标准单测case都很适用,而PowerMock可以去解决一些更难的问题(比如静态方法、私有方法等)。
PowerMock完美的弥补Mockito测试框架的不足,但笔者在实际运用过程中发现PowerMock似乎更容易产生报错,特此记录一些踩坑和注意点。
1、mock()与spy()
- 通过mock生成的对象,会拥有以前的对象的所有方法,但是方法中都没有了功能。
- 而通过spy,是通过调用clone()复制的,正常看来就和一个普通的对象一模一样,他的方法是能够进行模拟的。
2、doReturn和thenReturn
- 使用doReturn().when()时,被设桩方法不会被真的调用,而是直接调用了代理方法,返回在doReturn设置的值。
- 使用when().thenReturn()是有副作用的,被设桩方法会被执行,难免会产生影响。
doThrow/doNothing/thenThrow也是同理。所以建议最好使用doReturn。
3、classloader错误
一般通过加入注解:@PowerMockIgnore({YourPackagePath.* , xxx.xxx.*})来解决由于MockClassLoader造成的class加载错误;
通过这个注解可以让报错的类使用系统的ClassLoader来加载报错类。
4、方法参数
当使用PowerMockito时如果when在末尾,方法的参数必须是实例,不能是方法调用(如xxxx.method());
因为当用方法调用时,mockito会认为是开始stub,会报错:Unfinished-StubbingException;
如果when在thenReturn前就没有问题。
5、混用
PowerMockito和Mockito mock出来的对象不能相互使用,否则会抛出异常。
6、效率
看起来PowerMockito更好用,那是否可以直接全部使用powerMockito呢?
PowerMockito是对mockito的封装,理论上耗时是比Mockito多的,而且初始化的东西比Mockito多。如果能不用PowerMockito就能完成单测,那最好了。
总结
PowerMock之所以如此强大,是因为它使用了自定义类加载器和字节码操作来模拟静态方法,构造函数,final类和方法,私有方法,去除静态初始化器等等。通过使用自定义的类加载器,简化采用的IDE或持续集成服务器不需要做任何改变。在编写单元测试时,采用Mockito为主,PowerMock为辅的方式几乎就可以做到无所不能啦(实在不行还有反射…