我们先来看看PowerMock的依赖:
可以看出来,它有两个重要的依赖:javassist和objenesis。
javassist是一个修改java字节码的工具包,objenesis是一个绕过构造方法来实例化一个对象的工具包。由此看来,PowerMock的本质是通过修改字节码来实现对静态和final等方法的mock的。
@RunWith(PowerMockRunner.class)
public class TestClassUnderTest {
@Test
public void testCallArgumentInstance() {
showClassLoader("testCallArgumentInstance");
File file = PowerMockito.mock(File.class);
ClassUnderTest underTest = new ClassUnderTest();
PowerMockito.when(file.exists()).thenReturn(true);
Assert.assertTrue(underTest.callArgumentInstance(file));
}
@Test
@PrepareForTest(ClassUnderTest.class)
public void testCallInternalInstance() throws Exception {
showClassLoader("testCallInternalInstance");
File file = PowerMockito.mock(File.class);
ClassUnderTest underTest = new ClassUnderTest();
PowerMockito.whenNew(File.class).withArguments("bbb").thenReturn(file);
PowerMockito.when(file.exists()).thenReturn(true);
Assert.assertTrue(underTest.callInternalInstance("bbb"));
}
@Test
@PrepareForTest(ClassDependency.class)
public void testCallFinalMethod() {
showClassLoader("testCallFinalMethod");
ClassDependency depencency = PowerMockito.mock(ClassDependency.class);
ClassUnderTest underTest = new ClassUnderTest();
PowerMockito.when(depencency.isAlive()).thenReturn(true);
Assert.assertTrue(underTest.callFinalMethod(depencency));
}
private void showClassLoader(String methodName) {
System.out.println("=============="+methodName+"===============");
System.out.println("TestClassUnderTest: " + TestClassUnderTest.class.getClassLoader());
System.out.println("ClassUnderTest: " + ClassUnderTest.class.getClassLoader());
System.out.println("ClassDependency: " + ClassDependency.class.getClassLoader());
}
}
我们通过这段代码打印出来的ClassLoader,能让我们对PowerMock的实现原理有近一步的了解。
引用
==============testCallArgumentInstance===============
TestClassUnderTest: sun.misc.Launcher$AppClassLoader@19821f
ClassUnderTest: sun.misc.Launcher$AppClassLoader@19821f
ClassDependency: sun.misc.Launcher$AppClassLoader@19821f
==============testCallInternalInstance===============
TestClassUnderTest: org.powermock.core.classloader.MockClassLoader@117a8bd
ClassUnderTest: org.powermock.core.classloader.MockClassLoader@117a8bd
ClassDependency: org.powermock.core.classloader.MockClassLoader@117a8bd
==============testCallFinalMethod===============
TestClassUnderTest: org.powermock.core.classloader.MockClassLoader@1f42b49
ClassUnderTest: org.powermock.core.classloader.MockClassLoader@1f42b49
ClassDependency: org.powermock.core.classloader.MockClassLoader@1f42b49
下面是我总结的PowerMock的简单实现原理:
- 当某个测试方法被注解@PrepareForTest标注以后,在运行测试用例时,会创建一个新的org.powermock.core.classloader.MockClassLoader实例,然后加载该测试用例使用到的类(系统类除外)。
- PowerMock会根据你的mock要求,去修改写在注解@PrepareForTest里的class文件(当前测试类会自动加入注解中),以满足特殊的mock需求。例如:去除final方法的final标识,在静态方法的最前面加入自己的虚拟实现等。
- 如果需要mock的是系统类的final方法和静态方法,PowerMock不会直接修改系统类的class文件,而是修改调用系统类的class文件,以满足mock需求。
在没有看PowerMock源码之前,我一直很疑惑PowerMock是怎么mock系统类的final方法和静态方法的?难道它真的能修改了系统类的类文件,因为系统的类文件是被Boostarp ClassLoader加载的,应用程序无法修改它,所以就很好奇。看了源码之后,原来才发现PowerMock并没有修改系统类,而是修改了调用系统类的地方,这才豁然开朗它是如何mock系统类的行为的。
- 大小: 33.6 KB
分享到:
相关推荐
powermock powermock powermock powermock
全面介绍PowerMock的使用,帮助初学者彻底了解PowerMock的使用,提高代码的健壮性
Powermock是基于现有的mock框架,easymock和mockito而建立的一个非常强大的框架,它具备easymock和mockito所不具备的一些功能,该系列教材详细的说明了如何使用powermock的所有特性
powermock-classloading-xstream-1.4.7powermock-classloading-xstream-1.4.7powermock-classloading-xstream-1.4.7powermock-classloading-xstream-1.4.7powermock-classloading-xstream-1.4.7powermock-class...
赠送jar包:powermock-api-support-2.0.9.jar; 赠送原API文档:powermock-api-support-2.0.9-javadoc.jar; 赠送源代码:powermock-api-support-2.0.9-sources.jar; 赠送Maven依赖信息文件:powermock-api-support...
赠送jar包:powermock-api-mockito2-2.0.9.jar; 赠送原API文档:powermock-api-mockito2-2.0.9-javadoc.jar; 赠送源代码:powermock-api-mockito2-2.0.9-sources.jar; 赠送Maven依赖信息文件:powermock-api-...
powermock maven respo
赠送jar包:powermock-core-2.0.9.jar; 赠送原API文档:powermock-core-2.0.9-javadoc.jar; 赠送源代码:powermock-core-2.0.9-sources.jar; 赠送Maven依赖信息文件:powermock-core-2.0.9.pom; 包含翻译后的API...
什么时候需要Mock对象 什么是EasyMock EasyMock的优点和缺点 运行EasyMock需要的资源 EasyMock的基本使用步骤 什么是PowerMock 运行PowerMock需要的资源 PowerMock的扩展功能
PowerMock 也是一个单元测试模拟...PowerMock 的目的就是在当前已经被大家所熟悉的接口上通过添加极少的方法和注释来实现额外的功能,目前,PowerMock 仅支持 EasyMock 和 Mockito。 标签:PowerMock 单元测试
powermock 版本要求比较严格,请使用1.6及以上jdk
赠送jar包:powermock-module-junit4-2.0.9.jar; 赠送原API文档:powermock-module-junit4-2.0.9-javadoc.jar; 赠送源代码:powermock-module-junit4-2.0.9-sources.jar; 赠送Maven依赖信息文件:powermock-...
PowerMock实战手册。采用的是Junit+PowerMock+Mockito这样的组合来进行讲述。
使用powermock+jacoco,测试静态方法,测试覆盖率。环境是:IDEA+maven。 直接执行:mvn clean install,然后查看覆盖率:powermock-cover\target\site\jacoco\index.html
PowerMock资料,jar包 http://www.ibm.com/developerworks/cn/java/j-lo-powermock/
网上找了好多powermock的例子都不好用,一怒之下亲自挨个引入测试,最终得到这些jar,给需要的朋友,自己也留个备份。
powermock-easymock-junit-1.5.4.zip
tesunit junit easymock PowerMock
关于PowerMock Instant Mock Testing with PowerMock 7 Saying Hello World! (Simple) 8 Getting and installing PowerMock (Simple) 14 Mocking static methods (Simple) 22 Verifying method invocation (Simple)...
powermock-easymock-junit-1.6.1.zip