对于PowerMock的底层原理你了解多少呢?很多人表示,对这个原理不大清楚,那么下面就一起通过以下的文章内容来进行一下了解吧。
首先的话我们要来看一看PowerMock的依赖,PowerMock有着两个非常重要的依赖,一个是javassist,另外一个就是objenesis,下面分别来简单的对这两者进行一下介绍。
1、javassist
javassist是一个修改java字节码的工具包;
2、objenesis
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()); } }
下面来介绍一下PowerMock实现原理。
其实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的源码之后就发现,原来PowerMock其实并没有去修改系统类,它只是修改了调用系统类的地方,这样的话就十分的明朗了。
以上就是对PowerMock原理的一个简单小总结了,你都了解了吗?你还想了解更多和PowerMock相关的常见问题吗?请继续通过奇Q工具网来进行了解吧。
推荐阅读: