zoukankan      html  css  js  c++  java
  • PowerMockito使用详解

      一、PowerMock概述

          现如今比较流行的Mock工具如jMock,EasyMock,Mockito等都有一个共同的缺点:不能mock静态、final、私有方法等。而PowerMock能够完美的弥补以上三个Mock工具的不足。

          PowerMock是一个扩展了其它如EasyMock等mock框架的、功能更加强大的框架。PowerMock使用一个自定义类加载器和字节码操作来模拟静态方法,构造函数,final类和方法,私有方法,去除静态初始化器等等。通过使用自定义的类加载器,简化采用的IDE或持续集成服务器不需要做任何改变。熟悉PowerMock支持的mock框架的开发人员会发现PowerMock很容易使用,因为对于静态方法和构造器来说,整个的期望API是一样的。PowerMock旨在用少量的方法和注解扩展现有的API来实现额外的功能。目前PowerMock支持EasyMock和Mockito。

          二PowerMock入门    

          PowerMock有两个重要的注解:

          –@RunWith(PowerMockRunner.class)

          –@PrepareForTest( { YourClassWithEgStaticMethod.class })

          如果你的测试用例里没有使用注解@PrepareForTest,那么可以不用加注解@RunWith(PowerMockRunner.class),反之亦然。当你需要使用PowerMock强大功能(Mock静态、final、私有方法等)的时候,就需要加注解@PrepareForTest。

          三PowerMock基本用法

       (1) 普通Mock: Mock参数传递的对象

    //测试目标代码:
    public boolean callArgumentInstance(File file) {
        return file.exists();
    }
    
    //测试用例代码: 
    @Test
    public void testCallArgumentInstance() {
        File file = PowerMockito.mock(File.class);
        Source underTest = new Source();
        PowerMockito.when(file.exists()).thenReturn(true);
        Assert.assertTrue(underTest.callArgumentInstance(file));
    }

     说明:普通Mock不需要加@RunWith和@PrepareForTest注解。

       (2)  Mock方法内部new出来的对象

    //测试目标代码:
    public boolean callInternalInstance(String path) {
        File file = new File(path);
        return file.exists();
    }
     
    //测试用例代码:    
    @Test
    @PrepareForTest(Source.class)
    public void testCallInternalInstance() throws Exception
    {
        File file = PowerMockito.mock(File.class);
        Source underTest = new Source();
        PowerMockito.whenNew(File.class).withArguments("bbb").thenReturn(file);
        PowerMockito.when(file.exists()).thenReturn(true);
        Assert.assertTrue(underTest.callInternalInstance("bbb"));
    }

    说明:当使用PowerMockito.whenNew方法时,必须加注解@PrepareForTest和@RunWith。注解@PrepareForTest里写的类是需要mock的new对象代码所在的类。

       (3) Mock普通对象的final方法

    //测试目标代码:
    public class Source {
        public boolean callFinalMethod(SourceDepend refer) {
            return refer.isAlive();
        }
    }
    public class SourceDepend {
        public final boolean isAlive() {
            return false;
        }
    }
     
    //测试用例代码:
    @Test
    @PrepareForTest(SourceDepend.class)
    public void testCallFinalMethod()
    {
        SourceDepend depencency = PowerMockito.mock(SourceDepend.class);
        Source underTest = new Source();
        PowerMockito.when(depencency.isAlive()).thenReturn(true);
        Assert.assertTrue(underTest.callFinalMethod(depencency));
    }

    说明: 当需要mock final方法的时候,必须加注解@PrepareForTest和@RunWith。注解@PrepareForTest里写的类是final方法所在的类。 

       (4) Mock普通类的静态方法

    //测试目标代码:
    public boolean callStaticMethod() {
          return SourceDepend.isExist();
    }
    public static boolean isExist()
    {
        return false;
    }
    
    //测试用例代码:
    @Test
    @PrepareForTest(SourceDepend.class)
    public void testCallStaticMethod() {
        Source underTest = new Source();
        PowerMockito.mockStatic(SourceDepend.class);
        PowerMockito.when(SourceDepend.isExist()).thenReturn(true);
        Assert.assertTrue(underTest.callStaticMethod());
    }

    说明:当需要mock静态方法的时候,必须加注解@PrepareForTest和@RunWith。注解@PrepareForTest里写的类是静态方法所在的类。

      (5) Mock 私有方法

    //测试目标代码: 
    public boolean callPrivateMethod() {
        return isExist();
    }
    
    private boolean isExist() {
        return false;
    }
     
    //测试用例代码:  
    @Test
    @PrepareForTest(Source.class)
    public void testCallPrivateMethod() throws Exception
    {
        Source underTest = PowerMockito.mock(Source.class);
        PowerMockito.when(underTest.callPrivateMethod()).thenCallRealMethod();
        PowerMockito.when(underTest, "isExist").thenReturn(true);
        Assert.assertTrue(underTest.callPrivateMethod());
    } 
    

    说明:和Mock普通方法一样,只是需要加注解@PrepareForTest(ClassUnderTest.class),注解里写的类是私有方法所在的类。 

       (6) Mock系统类的静态和final方法 

    //测试目标代码:   
    public boolean callSystemFinalMethod(String str)
    {
        return str.isEmpty();
    }
    
    public String callSystemStaticMethod(String str)
    {
        return System.getProperty(str);
    }
     
    //测试用例代码:
    @Test
    @PrepareForTest(Source.class)
    public void testCallSystemStaticMethod()
    {
        Source underTest = new Source();
        PowerMockito.mockStatic(System.class);
        PowerMockito.when(System.getProperty("aaa")).thenReturn("bbb");
        Assert.assertEquals("bbb", underTest.callSystemStaticMethod("aaa"));
    }
    

    说明:和Mock普通对象的静态方法、final方法一样,只不过注解@PrepareForTest里写的类不一样 ,注解里写的类是需要调用系统方法所在的类。

          四、无所不能的PowerMock

           (1) 验证静态方法:

           PowerMockito.verifyStatic();
           Static.firstStaticMethod(param);

           (2) 扩展验证:

           PowerMockito.verifyStatic(Mockito.times(2)); // 被调用2次

         Static.thirdStaticMethod(Mockito.anyInt()); // 以任何整数值被调用

           (3) 更多的Mock方法

           http://code.google.com/p/powermock/wiki/MockitoUsage13

          五、PowerMock简单实现原理

           当某个测试方法被注解@PrepareForTest标注以后,在运行测试用例时,会创建一个新的org.powermock.core.classloader.MockClassLoader实例,然后加载该测试用例使用到的类(系统类除外)。

          PowerMock会根据你的mock要求,去修改写在注解@PrepareForTest里的class文件(当前测试类会自动加入注解中),以满足特殊的mock需求。例如:去除final方法的final标识,在静态方法的最前面加入自己的虚拟实现等。

           如果需要mock的是系统类的final方法和静态方法,PowerMock不会直接修改系统类的class文件,而是修改调用系统类的class文件,以满足mock需求。

  • 相关阅读:
    Eclipse安装Hadoop插件
    (转)Ubuntu14.0.4中hadoop2.4.0伪分布模式配置
    Hadoop--DataNode无法启动
    启动与关闭hadoop
    hadoop中执行命令时发生错误
    strings命令
    Deriving data from ElasticSearch Engine
    elasticsearch data importing
    reading words in your computer and changing to female voice, linux festival text2wave saving wav files
    DDNS client on a Linux machine
  • 原文地址:https://www.cnblogs.com/hunterCecil/p/5721468.html
Copyright © 2011-2022 走看看