我是靠谱客的博主 善良芒果,最近开发中收集的这篇文章主要介绍android powermock,使用PowerMock写Android单元测试,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

[TOC]

为什么用PowerMock

在写Android单测的时候,大家多为这几件事苦恼:

与Android API进行的交互,如何隔绝?

如何对private method/field进行mock?

如何对网络接口进行mock?

上面这几件事情可以通过PowerMock来进行解决。

PowerMock是什么

PowerMock是一个第三方开源框架,是对Mockito的扩展,主要围绕JUnit及TestN。可以对私有方法,私有属性,final方法进行mock。

本文主要围绕Junit + Mockito + PowerMock 组合进行

PowerMock怎么用

导入工程:

// Mockito

testCompile "org.mockito:mockito-core:2.8.9"

// PowerMock

testCompile "org.powermock:powermock-module-junit4:1.7.4"

testCompile "org.powermock:powermock-module-junit4-rule:1.7.4"

testCompile "org.powermock:powermock-api-mockito2:1.7.4"

testCompile "org.powermock:powermock-classloading-xstream:1.7.4"

PowerMock既然是Mockito的扩展,所以需要导入mockito-core。同时Mockito的版本与PowerMock的版本需要相对对应,具体可以参考PowerMock的Github主页。

mock静态方法/变量

public class MyClass {

private static int privateStaticFiled = 123;

public static int staticReturnMethod() {

return 1;

}

public static void staticVoidMethod() {

throw new IllegalStateException("should not go here");

}

private static void staticPrivateMethod(String a) {

throw new IllegalStateException(a);

}

}

所有的测试方法均在下面的类中进行

@RunWith(PowerMockRunner.class)

@PrepareForTest(MyClass.class)

public class MyClassTest {

}

mock非void类型的静态方法

@Test

public void staticReturnMethodTest() throws Exception {

PowerMockito.mockStatic(MyClass.class);

PowerMockito.when(MyClass.staticReturnMethod()).thenReturn(2);

Assert.assertEquals(2, MyClass.staticReturnMethod());

}

mock抛出异常:

PowerMockito.when(MyClass.staticReturnMethod()).thenThrow(new RuntimeException());

mock带参数void类型的静态方法

@Test

public void staticVoidMethodTest() throws Exception {

PowerMockito.mockStatic(MyClass.class);

PowerMockito.doNothing().when(MyClass.class, "staticVoidMethod", Mockito.anyInt());

}

方法计数:

MyClass.staticVoidMethod(123);//此处是对方法的调用

PowerMockito.verifyStatic(MyClass.class, Mockito.times(1));//本行及下面一行是记录方法调用及验证是否调用指定次数

MyClass.staticVoidMethod(123);

方法应答:

可以用来对方法内部逻辑进行mock

PowerMockito.doAnswer(new Answer() {

@Override

public Void answer(InvocationOnMock invocation) throws Throwable {

Object[] args = invocation.getArguments();

return null;

}

}).when(MyClass.class, "staticVoidMethod", Mockito.anyInt());

mock私有静态变量

Whitebox.setInternalState(myClass,"privateStaticFiled",789);

mock私有方法/变量

public class MyClass {

private int privateFiled = 123;

private int privateReturnMethod() {

return 1;

}

}

测试方法写到如下类中:

@RunWith(PowerMockRunner.class)

public class MyClassTest {

}

带返回值的私有方法

MyClass myClass = new MyClass();

PowerMockito.doReturn(123).when(myClass,"privateReturnMethod");

同时doReturn可以换成doAnswer,doNothing等等

私有属性

Whitebox.setInternalState(myClass,"privateFiled",789);

mock构造方法

public class MyClass{

public boolean newMethod(String path) {

File file = new File(path);

return file.exists();

}

}

对构造方法进行mock

File file = PowerMockito.mock(File.class);

MyClass myClass = new MyClass();

PowerMockito.whenNew(File.class).withArguments("abc").thenReturn(file);

PowerMockito.when(file.exists()).thenReturn(true);

Assert.assertTrue(myClass.newMethod("abc"));

PowerMock原理简单剖析

代替系统的ClassLoader加载Class

PowerMock实现了ClassLoader

java.lang.ClassLoader

|-javassist.Loader

|-org.powermock.core.classloader.DeferSupportingClassLoader

|-org.powermock.core.classloader.MockClassLoader

在MockClassLoaderFactory中被创建

public ClassLoader create() {

final String[] classesToLoadByMockClassloader = makeSureArrayContainsTestClassName(this.classesToLoadByMockClassloader, testClass.getName());

final ClassLoader mockLoader;

if (isContextClassLoaderShouldBeUsed(classesToLoadByMockClassloader)) {//判断是否应该使用MockClassLoader

mockLoader = Thread.currentThread().getContextClassLoader();

} else {

mockLoader = createMockClassLoader(classesToLoadByMockClassloader);

}

return mockLoader;

}

在AbstractCommonTestSuiteChunkerImpl中被调用时:

createNewClassloader(testClass, new String[]{MockClassLoader.MODIFY_ALL_CLASSES},ignorePackagesExtractor.getPackagesToIgnore(testClass), extraTransformers);

然而MockClassLoader.MODIFY_ALL_CLASSES = *可以判断基本会对使用@RunWith(PowerMockRunner.class)注解白标注的测试类使用MockClassLoader加载。

使用javassist修改字节码

在org.powermock.core.transformers包下AbstractMainMockTransformer类及其派生类中动态修改了被测类的字节码,根据测试类中的调用规则,生成了新的字节码文件替代原有字节码文件。

总结

通过上述分析,基本上可以判断PowerMock通过使用MockClassLoader替换系统ClassLoader,在类加载时动态生成了被测类的替代字节码文件。

最后

以上就是善良芒果为你收集整理的android powermock,使用PowerMock写Android单元测试的全部内容,希望文章能够帮你解决android powermock,使用PowerMock写Android单元测试所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(46)

评论列表共有 0 条评论

立即
投稿
返回
顶部