`
qicen
  • 浏览: 47462 次
  • 性别: 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依赖jar文件.rar

    这个压缩包可能是用户在尝试多种方法后,最终成功配置PowerMock并进行单元测试的成果,为了方便其他开发者使用和避免重蹈覆辙,他分享了这些必要的依赖。 描述中提到的"网上找了好多powermock的例子都不好用,一怒...

    使用PowerMock来Mock静态函数

    对于描述中提到的博客链接,虽然没有实际内容,但可以假设博主分享了如何配置和使用PowerMock进行静态方法模拟的步骤。一般步骤包括: 1. 引入PowerMock依赖:在项目构建文件(如Maven的pom.xml或Gradle的build....

    PowerMock实战手册.pdf

    PowerMock的HelloWorld示例通常会展示如何使用PowerMock创建一个简单的测试用例,比如模拟一个静态方法来获取员工数量,并创建一个员工对象。 #### 重点API解释 - **Mock**:创建一个mock对象,用于模拟方法调用。...

    Powermock:一个Powercord插件,可让您模拟某人

    安装和使用Powermock插件需要一定的技术知识,包括了解如何配置Powercord环境、安装插件以及阅读和理解插件源代码。用户需要下载`Powermock-master`压缩包,解压后将内容放入Powercord的插件目录,并重启客户端以使...

    mockjson:获取测试数据

    6. **团队协作**:如果在一个团队中工作,MockJSON 还支持权限管理和分享功能,使得团队成员可以共同维护和使用测试数据。 7. **集成其他工具**:MockJSON 可以与诸如 Postman、Jest 等测试工具结合使用,进一步...

    方成:手机京东,持续集成中的自动化实践

    在测试阶段,测试人员可能使用到错误的测试包,验证问题时往往遇到困难,测试工具的使用复杂度高。至于QA阶段,灰度期间出现的问题类型难以辨识,集成测试与灰度测试的数据对比困难,现有流程的完美性也常常受到质疑...

    文件下载

    源码部分可能展示了如何在实际项目中创建和使用mock对象,而工具部分可能介绍了流行的mocking框架,如上述的Moq和Mockito,以及其他如PowerMock、JMock等。 在单元测试中,mock对象常用于测试驱动开发(TDD)和行为...

    TestRepo:迈克尔·J·柯里(Michael J.Currie)的GitHub测试实验室

    这个测试实验室可能涵盖了单元测试、集成测试、性能测试、压力测试等多个方面的内容,同时,也可能涉及到Mockito、PowerMock等模拟工具的使用,以及如何利用IDE如IntelliJ IDEA或Eclipse进行测试开发。通过分析和...

Global site tag (gtag.js) - Google Analytics