`
qicen
  • 浏览: 47368 次
  • 性别: Icon_minigender_1
  • 来自: 武汉
文章分类
社区版块
存档分类
最新评论

PowerMock简单实现原理

阅读更多
我们先来看看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

    然而,当被测试的代码中包含静态方法调用、依赖于系统时间或使用了不可变的类(如 `java.lang.System`、`java.util.Date` 等)时,实现这样的隔离就变得困难。PowerMock 提供了一种方式来处理这些问题,使得测试更加...

    powermock源码 详细学习好帮手

    在“powermock源码 详细学习好帮手”这个资源中,你将能够深入理解PowerMock的工作原理,以及它是如何实现这些高级模拟功能的。源码分析是理解任何软件库的关键,特别是对于想要优化测试策略或定制库行为的开发者来...

    汪文君powermock实战教学

    9. **Answer接口的使用**:通过实现Answer接口,你可以自定义方法调用的返回值,进一步控制模拟对象的行为。 10. **Spy的使用和私有方法的mock**:Spy是Mock的一种扩展,允许部分真实对象的行为与模拟行为结合。...

    powermock依赖jar文件.rar

    Mocking框架如PowerMock使得开发者能够模拟复杂的对象行为,尤其是对静态方法、构造器、私有方法和final类的模拟,这在传统的单元测试中通常是难以实现的。PowerMock与JUnit结合使用,提供了强大的测试能力。下面...

    powermock-core-2.0.9-API文档-中英对照版.zip

    赠送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入门”中,读者将学习到PowerMock的基本使用场景、一个简单的“Hello World”示例以及重点API的解释。这些内容都是为了帮助读者快速上手PowerMock。 在后续章节中,将会进一步深入讲解PowerMock的...

    powermock单元测试

    通过分析这些代码,我们可以更深入地理解PowerMock的工作原理和使用方式。 总的来说,PowerMock增强了Java单元测试的能力,使得我们能够覆盖到原本难以触及的代码角落,提高了测试覆盖率和代码质量。然而,也需要...

    powerMock的测试样例集合

    通过仔细研究这些示例,你可以加深对PowerMock工作原理的理解,并学会如何在自己的项目中有效地使用它。 总之,"powerMock的测试样例集合"是一个宝贵的资源,它涵盖了PowerMock的主要功能,并通过实践案例帮助你...

    PowerMock实战手册

    Junit的断言方法和注解使得测试编写简单直观,而PowerMock与Junit的集成,让开发者可以在Junit测试中利用PowerMock的强大功能。 Mockito是另一个流行的mocking框架,它主要用于创建和配置mock对象,以便在测试中...

    PowerMock.zip

    例如,以下是一个简单的PowerMock示例: ```java @RunWith(PowerMockRunner.class) @PrepareForTest({SomeStaticClass.class}) public class MyTestClass { @Test public void testWithStaticMethod() { ...

    powermock maven respo

    1. **PowerMock**:PowerMock是Java单元测试的一个扩展,它通过使用Java代理和字节码操纵技术来实现对难以或无法模拟的Java行为的模拟。它可以用于测试以下情况: - 静态方法:在大多数情况下,静态方法不是可测试...

    使用PowerMock来Mock静态函数

    首先,理解PowerMock的工作原理是关键。它通过字节码操作(Bytecode Manipulation)来改变类的加载方式,从而允许我们在运行时修改类的行为。在Mockito中,我们通常使用`@RunWith(PowerMockRunner.class)`注解来启动...

    powermock-classloading-xstream-1.4.7

    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...

    powermock-module-junit4-2.0.9-API文档-中英对照版.zip

    赠送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-mockito-junit-1.6.2.zip

    PowerMock通过字节码操作(Bytecode Manipulation)实现这些功能,使得测试更加灵活和全面。在实际项目中,当存在难以或无法直接测试的代码时,PowerMock可以提供解决方案。 2. Mockito Mockito是一个流行的Java...

    EasyMock and PowerMock入门PPT

    EasyMock是一个强大的Java库,用于创建模拟对象(Mock Objects),它使得单元测试变得更加简单。在测试过程中,模拟对象可以替代真实的依赖,这样我们就可以专注于测试单个方法,而不用担心其他部分的复杂性。...

    powermock-easymock-junit-1.5.4.zip

    JUnit框架简洁易用,使得测试代码的编写和维护变得简单。当与PowerMock和EasyMock结合时,JUnit可以更全面地测试复杂的应用程序。 在"powermock-easymock-junit-1.5.4.zip"这个压缩包中,可能包含以下内容: 1. ...

    powermock-api-support-2.0.9-API文档-中英对照版.zip

    赠送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...

Global site tag (gtag.js) - Google Analytics