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

PowerMock使用分享

阅读更多
单元测试是对应用中的某一个模块的功能进行验证。在单元测试中,我们常遇到的问题是依赖的模块尚未开发完成或者被测试模块需要和一些不容易构造、比较复杂的对象进行交互。另外,由于不能肯定其它模块的正确性,我们也无法确定测试中发现的问题是由哪个模块引起的。所谓的mock,就是指,如果我们写的代码依赖于某些对象,而这些对象又很难手动创建,那么就使用一个虚拟的对象来完成单元测试。在java界现在比较流行的mock工具有:
jMock: http://jmock.org/
EasyMock: http://easymock.org/
Mockito: http://code.google.com/p/mockito/
但是这些mock工具都有一些缺陷,就是不能mock静态、final、私有方法等,而powermock能够做到。
Power Mock:http://code.google.com/p/powermock/
Power Mock有两个版本,一个是基于easymock实现的,另一个是基于mockito实现的。

备注:如果你使用JaCoCo作为你的code coverage插件的话,那么所有写在注解@PrepareForTest里的类的覆盖率都是零。这是JaCoCo插件的限制或者说是Bug:https://github.com/jacoco/eclemma/issues/15,而且它并不打算修改这个Bug。所以如果你想使用PowerMock提升覆盖率的话,请使用其它的code coverage插件:cobertura
Sonar里默认的code coverage插件是JaCoCo。


下面我将以Power Mock的mockito的版本来讲述如何使用Power Mock。
测试目标类:
public class ClassUnderTest {

    public boolean callArgumentInstance(File file) {
        return file.exists();
    }
    
    public boolean callInternalInstance(String path) {
        File file = new File(path);
        return file.exists();
    }
    
    public boolean callFinalMethod(ClassDependency refer) {
        return refer.isAlive();
    }
    
    public boolean callSystemFinalMethod(String str) {
        return str.isEmpty();
    }
    
    public boolean callStaticMethod() {
        return ClassDependency.isExist();
    }
    
    public String callSystemStaticMethod(String str) {
        return System.getProperty(str);
    }
    
    public boolean callPrivateMethod() {
        return isExist();
    }
    
    private boolean isExist() {
        // do something
        return false;
    }
}

依赖类:
public class ClassDependency {

    public static boolean isExist() {
        // do something
        return false;
    }
    
    public final boolean isAlive() {
        // do something
        return false;
    }
}


接下来,对6个测试用例进行逐个的讲解。
首先需要使用@RunWith(PowerMockRunner.class)将测试用例的runner改为PowerMockRunner
1、testCallArgumentInstance:Mock参数传递的对象
    @Test
    public void testCallArgumentInstance() {
        File file = PowerMockito.mock(File.class);
        ClassUnderTest underTest = new ClassUnderTest();
        PowerMockito.when(file.exists()).thenReturn(true);
        Assert.assertTrue(underTest.callArgumentInstance(file));
    }

需要mock的对象是由参数传进去的,这是最普通的一种mock方式,jMock,EasyMock,Mockito都能实现。
步骤:
a、通过PowerMockito.mock(File.class)创建出一个mock对象
b、然后再通过PowerMockito.when(file.exists()).thenReturn(false);来指定这个mock对象具体的行为
c、再将mock对象作为参数传递个测试方法,执行测试方法。

2、testCallInternalInstance:Mock方法内部new出来的对象
    @Test
    @PrepareForTest(ClassUnderTest.class)
    public void testCallInternalInstance() throws Exception {
        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"));
    }

需要mock的对象是在方法内部new出来的,这是一种比较常见的mock方式。
步骤(已经讲过的步骤省略):
a、通过PowerMockito.whenNew(File.class).withArguments("bbb").thenReturn(file)来指定当以参数为bbb创建File对象的时候,返回已经mock的File对象。
b、在测试方法之上加注解@PrepareForTest(ClassUnderTest.class),注解里写的类是需要mock的new对象代码所在的类。

3、testCallFinalMethod:Mock普通对象的final方法。
    @Test
    @PrepareForTest(ClassDependency.class)
    public void testCallFinalMethod() {
        
        ClassDependency depencency = PowerMockito.mock(ClassDependency.class);
        ClassUnderTest underTest = new ClassUnderTest();
        PowerMockito.when(depencency.isAlive()).thenReturn(true);
        Assert.assertTrue(underTest.callFinalMethod(depencency));
    }

Mock的步骤和之前的一样,只是需要在测试方法之上加注解@PrepareForTest(ClassDependency.class),注解里写的类是需要mock的final方法所在的类。

4、testCallStaticMethod:Mock静态方法。
    @Test
    @PrepareForTest(ClassDependency.class)
    public void testCallStaticMethod() {
        ClassUnderTest underTest = new ClassUnderTest();
        PowerMockito.mockStatic(ClassDependency.class);
        PowerMockito.when(ClassDependency.isExist()).thenReturn(true);
        Assert.assertTrue(underTest.callStaticMethod());
    }

步骤:
a、通过PowerMockito.mockStatic(ClassDependency.class);表示需要mock这个类里的静态方法
b、在测试方法之上加注解@PrepareForTest(ClassDependency.class),注解里写的类是需要mock的静态方法所在的类。

5、testCallSystemStaticMethod:Mock JDK中类的静态方法。
   testCallSystemFinalMethod:Mock JDK对象的final方法。

 
  @Test
    @PrepareForTest(ClassUnderTest.class)
    public void testCallSystemStaticMethod() {
        ClassUnderTest underTest = new ClassUnderTest();
        PowerMockito.mockStatic(System.class);
        PowerMockito.when(System.getProperty("aaa")).thenReturn("bbb");
        Assert.assertEquals("bbb", underTest.callJDKStaticMethod("aaa"));
    }

    @Test
    @PrepareForTest(ClassUnderTest.class)
    public void testCallSystemFinalMethod() {
        
        String str = PowerMockito.mock(String.class);
        ClassUnderTest underTest = new ClassUnderTest();
        PowerMockito.when(str.isEmpty()).thenReturn(false);
        Assert.assertFalse(underTest.callJDKFinalMethod(str));
    }

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

6、testCallPrivateMethod:Mock私有方法。
    @Test
    @PrepareForTest(ClassUnderTest.class)
    public void testCallPrivateMethod() throws Exception {
        ClassUnderTest underTest = PowerMockito.mock(ClassUnderTest.class);
        PowerMockito.when(underTest.callPrivateMethod()).thenCallRealMethod();
        PowerMockito.when(underTest, "isExist").thenReturn(true);
        Assert.assertTrue(underTest.callPrivateMethod());
    }

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

完整的测试用例类:
@RunWith(PowerMockRunner.class)
public class TestClassUnderTest {

    @Test
    public void 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 {
        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() {
        
        ClassDependency depencency = PowerMockito.mock(ClassDependency.class);
        ClassUnderTest underTest = new ClassUnderTest();
        PowerMockito.when(depencency.isAlive()).thenReturn(true);
        Assert.assertTrue(underTest.callFinalMethod(depencency));
    }
    
    @Test
    @PrepareForTest(ClassUnderTest.class)
    public void testCallSystemFinalMethod() {
        
        String str = PowerMockito.mock(String.class);
        ClassUnderTest underTest = new ClassUnderTest();
        PowerMockito.when(str.isEmpty()).thenReturn(false);
        Assert.assertFalse(underTest.callSystemFinalMethod(str));
    }
    
    @Test
    @PrepareForTest(ClassDependency.class)
    public void testCallStaticMethod() {
        ClassUnderTest underTest = new ClassUnderTest();
        PowerMockito.mockStatic(ClassDependency.class);
        PowerMockito.when(ClassDependency.isExist()).thenReturn(true);
        Assert.assertTrue(underTest.callStaticMethod());
    }
    
    @Test
    @PrepareForTest(ClassUnderTest.class)
    public void testCallSystemStaticMethod() {
        ClassUnderTest underTest = new ClassUnderTest();
        PowerMockito.mockStatic(System.class);
        PowerMockito.when(System.getProperty("aaa")).thenReturn("bbb");
        Assert.assertEquals("bbb", underTest.callSystemStaticMethod("aaa"));
    }
    
    @Test
    @PrepareForTest(ClassUnderTest.class)
    public void testCallPrivateMethod() throws Exception {
        ClassUnderTest underTest = PowerMockito.mock(ClassUnderTest.class);
        PowerMockito.when(underTest.callPrivateMethod()).thenCallRealMethod();
        PowerMockito.when(underTest, "isExist").thenReturn(true);
        Assert.assertTrue(underTest.callPrivateMethod());
    }
}
分享到:
评论
1 楼 静坛使者 2018-01-10  
感谢博主,确实遇到jacoco和PrepareForTest组合使用 造成覆盖率未统计的问题了

相关推荐

    powermock

    powermock powermock powermock powermock

    PowerMock实战

    全面介绍PowerMock的使用,帮助初学者彻底了解PowerMock的使用,提高代码的健壮性

    powermock单元测试

    powermock1.4.9.jar和powermock测试静态方法和私有方法的测试代码,大家都知道easymock不能测试这些,配合使用和单元测试更加完善。

    汪文君powermock实战教学

    Powermock是基于现有的mock框架,easymock和mockito而建立的一个非常强大的框架,它具备easymock和mockito所不具备的一些功能,该系列教材详细的说明了如何使用powermock的所有特性

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

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

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

    EasyMock and PowerMock入门PPT

    什么时候需要Mock对象 什么是EasyMock EasyMock的优点和缺点 运行EasyMock需要的资源 EasyMock的基本使用步骤 什么是PowerMock 运行PowerMock需要的资源 PowerMock的扩展功能

    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 版本要求比较严格,请使用1.6及以上jdk

    powermock-mockito-demo:使用springboot的powermock-mockito-demo

    使用在springboot项目中使用powermock-mockito进行单元测试,演示mock static、private、whenNew、exception的测试。 注意 示例使用spring-boot 2.0.3.RELEASE 它间接引用 junit-4.12 mockito-core-2.15.0 但是官网...

    powermock maven respo

    powermock maven respo

    powermock-cover.zip

    使用powermock+jacoco,测试静态方法,测试覆盖率。环境是:IDEA+maven。 直接执行:mvn clean install,然后查看覆盖率:powermock-cover\target\site\jacoco\index.html

    使用PowerMock来Mock静态函数

    NULL 博文链接:https://never-forget.iteye.com/blog/1717297

    powerMock的测试样例集合

    学习powermock实战手册,自己写的若干例子,mock static、final ,mock 局部变量、成员变量、Answer接口、ArgumentMatcher

    单元测试模拟框架PowerMock.zip

    PowerMock 也是一个单元测试模拟框架,它是在其它单元测试模拟框架的基础上做出的扩展。通过提供定制的类加载器以及一些字节码篡改技巧的应用,PowerMock 现了对静态方法、构造方法、私有方法以及 Final 方法的模拟...

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

    赠送jar包:powermock-module-junit4-common-2.0.9.jar; 赠送原API文档:powermock-module-junit4-common-2.0.9-javadoc.jar; 赠送源代码:powermock-module-junit4-common-2.0.9-sources.jar; 赠送Maven依赖信息...

    powermock依赖jar文件.rar

    网上找了好多powermock的例子都不好用,一怒之下亲自挨个引入测试,最终得到这些jar,给需要的朋友,自己也留个备份。

    PowerMock实战手册

    PowerMock实战手册。采用的是Junit+PowerMock+Mockito这样的组合来进行讲述。

Global site tag (gtag.js) - Google Analytics