我们先来看看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
分享到:
相关推荐
然而,当被测试的代码中包含静态方法调用、依赖于系统时间或使用了不可变的类(如 `java.lang.System`、`java.util.Date` 等)时,实现这样的隔离就变得困难。PowerMock 提供了一种方式来处理这些问题,使得测试更加...
在“powermock源码 详细学习好帮手”这个资源中,你将能够深入理解PowerMock的工作原理,以及它是如何实现这些高级模拟功能的。源码分析是理解任何软件库的关键,特别是对于想要优化测试策略或定制库行为的开发者来...
9. **Answer接口的使用**:通过实现Answer接口,你可以自定义方法调用的返回值,进一步控制模拟对象的行为。 10. **Spy的使用和私有方法的mock**:Spy是Mock的一种扩展,允许部分真实对象的行为与模拟行为结合。...
Mocking框架如PowerMock使得开发者能够模拟复杂的对象行为,尤其是对静态方法、构造器、私有方法和final类的模拟,这在传统的单元测试中通常是难以实现的。PowerMock与JUnit结合使用,提供了强大的测试能力。下面...
赠送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...
在“二、PowerMock入门”中,读者将学习到PowerMock的基本使用场景、一个简单的“Hello World”示例以及重点API的解释。这些内容都是为了帮助读者快速上手PowerMock。 在后续章节中,将会进一步深入讲解PowerMock的...
通过分析这些代码,我们可以更深入地理解PowerMock的工作原理和使用方式。 总的来说,PowerMock增强了Java单元测试的能力,使得我们能够覆盖到原本难以触及的代码角落,提高了测试覆盖率和代码质量。然而,也需要...
通过仔细研究这些示例,你可以加深对PowerMock工作原理的理解,并学会如何在自己的项目中有效地使用它。 总之,"powerMock的测试样例集合"是一个宝贵的资源,它涵盖了PowerMock的主要功能,并通过实践案例帮助你...
Junit的断言方法和注解使得测试编写简单直观,而PowerMock与Junit的集成,让开发者可以在Junit测试中利用PowerMock的强大功能。 Mockito是另一个流行的mocking框架,它主要用于创建和配置mock对象,以便在测试中...
例如,以下是一个简单的PowerMock示例: ```java @RunWith(PowerMockRunner.class) @PrepareForTest({SomeStaticClass.class}) public class MyTestClass { @Test public void testWithStaticMethod() { ...
1. **PowerMock**:PowerMock是Java单元测试的一个扩展,它通过使用Java代理和字节码操纵技术来实现对难以或无法模拟的Java行为的模拟。它可以用于测试以下情况: - 静态方法:在大多数情况下,静态方法不是可测试...
首先,理解PowerMock的工作原理是关键。它通过字节码操作(Bytecode Manipulation)来改变类的加载方式,从而允许我们在运行时修改类的行为。在Mockito中,我们通常使用`@RunWith(PowerMockRunner.class)`注解来启动...
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-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通过字节码操作(Bytecode Manipulation)实现这些功能,使得测试更加灵活和全面。在实际项目中,当存在难以或无法直接测试的代码时,PowerMock可以提供解决方案。 2. Mockito Mockito是一个流行的Java...
EasyMock是一个强大的Java库,用于创建模拟对象(Mock Objects),它使得单元测试变得更加简单。在测试过程中,模拟对象可以替代真实的依赖,这样我们就可以专注于测试单个方法,而不用担心其他部分的复杂性。...
赠送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通过字节码操作来实现这些功能,因此它需要一个特殊的类加载器来运行测试。 1. **Mocking静态方法**:在某些情况下,静态方法可能对系统行为有直接影响,PowerMock允许我们mock这些静态方法,从而隔离被...