简介

Mockito无法实现对静态函数、构造函数、私有函数、Final 等函数的模拟,PowerMock是一个Java模拟框架,可用于解决通常被认为很难甚至无法测试的测试问题。 使用PowerMock,可以模拟静态方法,删除静态初始化程序,允许模拟而不依赖注入等等。 PowerMock通过在执行测试时在运行时修改字节代码来完成这些技巧。
本文主要是介绍PowerMock 在 Mockito 框架上扩展的功能。
PowerMock提供了一个名为“PowerMockito”的类,用于创建模拟/对象/类并验证,其他仍然可以使用Mockito来设置和验证(例如times(),anyInt())。

maven使用配置

对junit来说有版本不同的话,配置也不相同,我们这里只给出junit4.4以上版本,mockito2.x版本的maven配置,其他的可以参考github官方介绍:https://github.com/powermock/powermock/wiki/Getting-Started

<properties><powermock.version>1.7.1</powermock.version>
</properties>
<dependencies><dependency><groupId>org.powermock</groupId><artifactId>powermock-module-junit4</artifactId><version>${powermock.version}</version><scope>test</scope></dependency><dependency><groupId>org.powermock</groupId><artifactId>powermock-api-mockito2</artifactId><version>${powermock.version}</version><scope>test</scope></dependency>
</dependencies>

所有用到PowerMock的类都需要@RunWith(PowerMockRunner.class)和@PrepareForTest注解。

1. mock静态方法

(1) 首先在测试类上添加@PrepareForTest注解

@PrepareForTest(Static.class) // Static.class 是包含静态方法的类。

(2) 调用PowerMockito.mockStatic()方法来模拟Static.class

PowerMockito.mockStatic(Static.class);

(3) 使用Mockito.when()来模拟期望的结果

Mockito.when(Static.firstStaticMethod(param)).thenReturn(value);

(4) 验证
第一步:调用PowerMockito.verifyStatic(Static.class)验证行为;
第二步:然后调用Static.class的静态方法进行验证

PowerMockito.verifyStatic(Static.class); // 1
Static.firstStaticMethod(param); // 2

下面给一个完整的示例:
定义一个包含静态方法的类Hello:

public class Hello {public static int getValue1(){return 1;}public static int getValue2(){return 2;}}

下面是测试代码:

@RunWith(PowerMockRunner.class)
@PrepareForTest(Hello.class)
public class PowerMockTest {@Testpublic void testGetValue() {PowerMockito.mockStatic(Hello.class);Mockito.when(Hello.getValue1()).thenReturn(444);Mockito.when(Hello.getValue2()).thenReturn(666);assertEquals(444, Hello.getValue1());assertEquals(666, Hello.getValue2());}
}

2. mock构造方法

比如有一个要测试的类Directory :

public class Directory {public boolean create(String path) {File file = new File(path);if (file.exists()) {throw new IllegalArgumentException("path already exists");}return file.mkdirs();}
}

为了测试create方法,我们可以对File进行mock,并对file的方法进行打桩,先看一下测试代码:

@RunWith(PowerMockRunner.class)
@PrepareForTest(Directory.class)
public class DirectoryTest {@Testpublic void testCreate() throws Exception {String path = "mocked path";File mockFile = PowerMockito.mock(File.class);PowerMockito.whenNew(File.class).withArguments(path).thenReturn(mockFile);PowerMockito.when(mockFile.exists()).thenReturn(false);PowerMockito.when(mockFile.mkdirs()).thenReturn(true);assertTrue(new Directory().create(path));}
}

大致步骤如下
(1)通过PowerMockito.mock(File.class)来mock一个File对象;
(2)使用 whenNew().withArguments().thenReturn() 语句实现对具体类的构造函数的模拟操作;
(3)然后对于之前创建的模拟对象 mockFile使用 When().thenReturn() 语句,即可实现需要的所有功能,从而实现对被测对象的覆盖测试。

3. mock私有方法和静态方法

为了实现对类的私有方法或者是 Final 方法的模拟操作,需要 PowerMock 提供的另外一项技术:局部模拟。

在之前的介绍的模拟操作中,我们总是去模拟一整个类或者对象,然后使用 When().thenReturn()语句去指定其中值得关心的部分函数的返回值,从而达到搭建各种测试环境的目标。对于没有使用 When().thenReturn()方法指定的函数,系统会返回各种类型的默认值(具体值可参考官方文档)。

局部模拟则提供了另外一种方式,在使用局部模拟时,被创建出来的模拟对象依然是原系统对象,虽然可以使用方法 When().thenReturn()来指定某些具体方法的返回值,但是没有被用此函数修改过的函数依然按照系统原始类的方式来执行。

这种局部模拟的方式的强大之处在于,除开一般方法可以使用之外,Final 方法和私有方法一样可以使用。

参考如下所示的被测代码:

public final class PrivatePartialMockingExample {public String methodToTest() {return methodToMock("input");}private String methodToMock(String input) {return "REAL VALUE = " + input;}
}

为了保持单元测试的纯洁性,在测试方法 methodToTest()时,我们不希望受到私有函数 methodToMock()实现的干扰,为了达到这个目的,我们使用刚提到的局部模拟方法来实现 , 实现方式如下:

import  org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;import static org.junit.Assert.assertEquals;
import static org.powermock.api.mockito.PowerMockito.spy;
import static org.powermock.api.mockito.PowerMockito.verifyPrivate;
import static org.powermock.api.mockito.PowerMockito.when;@RunWith(PowerMockRunner.class)
@PrepareForTest(PrivatePartialMockingExample.class)
public class PrivatePartialMockingExampleTest {@Testpublic void demoPrivateMethodMocking() throws Exception {final String expected = "TEST VALUE";final String nameOfMethodToMock = "methodToMock";final String input = "input";PrivatePartialMockingExample underTest = spy(new PrivatePartialMockingExample());/* Setup the expectation to the private method using the method name */ when(underTest, nameOfMethodToMock, input).thenReturn(expected);assertEquals(expected, underTest.methodToTest());// Optionally verify that the private method was actually calledverifyPrivate(underTest).invoke(nameOfMethodToMock, input);}
}

可以发现,为了实现局部模拟操作,用来创建模拟对象的函数从 mock() 变成了 spy(),操作对象也从类本身变成了一个具体的对象。同时,When() 函数也使用了不同的版本:在模拟私有方法或者是 Final 方法时,When() 函数需要依次指定模拟对象、被指定的函数名字以及针对该函数的输入参数列表。

后半部分摘自:https://www.ibm.com/developerworks/cn/java/j-lo-powermock/index.html

PowerMock与Mockito使用教程相关推荐

  1. java+mock+例子_java – 如何使用PowerMock和Mockito模拟枚举类的实例?

    我试着按照这个非常相似的问题的答案提供的例子,但它对我不起作用.我收到以下错误消息: java.lang.IllegalArgumentException: Cannot subclass final ...

  2. powermockito教程_Mockito与PowerMock的使用基础教程

    一.Mockito与PowerMock简述 Mockito与PowerMock都是Java流行的一种Mock框架,使用Mock技术能让我们隔离外部依赖以便对我们自己的业务逻辑代码进行单元测试,在编写单 ...

  3. Mockito 简明教程

    原文同步至 http://waylau.com/mockito-quick-start/ Mock 测试是单元测试的重要方法之一.本文介绍了基于 Java 语言的 Mock 测试框架 -- Mocki ...

  4. mockito简要教程

    1 mockito概述 Mockito is a mocking framework that tastes really good. It lets you write beautiful test ...

  5. Mockito使用教程

    什么是 Mockito Mockito 是一个强大的用于 Java 开发的模拟测试框架, 通过 Mockito 我们可以创建和配置 Mock 对象, 进而简化有外部依赖的类的测试. 使用 Mockit ...

  6. Mockito详细教程

    前言 单元测试(UT) 工作一段时间后,才真正意识到代码质量的重要性.虽然囫囵吞枣式地开发,表面上看来速度很快,但是给后续的维护与拓展制造了很多隐患. 作为一个想专业但还不专业的程序员,通过构建覆盖率 ...

  7. Mock框架Mockito入门教程

    在开发中,我们经常会依赖同事或者第三方提供的接口,如果该接口无法正常工作:比如接口正在修复,或者网络异常等.那么便会对需要依赖该接口的开发造成很大影响. 遇到这种情况,我们可能会想到模拟该接口以提供正 ...

  8. dubbo应用程序的单元测试环境搭建(springtest,powermock,mockito)

    转:http://blog.csdn.net/yys79/article/details/66472797 最近,项目中频繁用到dubbo,而且java工程用引用了几十个关联系统的服务(如用户认证,基 ...

  9. 使用MRUnit,Mockito和PowerMock进行Hadoop MapReduce作业的单元测试

    0.preliminary 环境搭建 Setup development environment Download the latest version of MRUnit jar from Apac ...

最新文章

  1. A + B Problem
  2. 如何记录2秒内实现1800度转体+翻腾,百度智能云黑科技教你看懂跳水
  3. shell实例第2讲:获取随机字符串
  4. jvm 调优_Java架构—JVM调优
  5. 《走遍中国》珍藏版(十)
  6. SQLServer 数据库主体在该数据库中拥有 架构,无法删除解决方法
  7. 易用宝项目记录day2-框架搭建
  8. Origin 2021 创建双y轴
  9. Latex科技论文写作
  10. SQL Server 数据库维护计划
  11. ctfshow 做题 MISC入门 模块 21~30
  12. 判断计算机电脑是否通电,电脑日常维护:查看硬盘通电时间,判断性能
  13. Linux日志切割神器Logrotate的原理和配置详解,建议收藏!!!
  14. 配置node服务器并且链接微信公众号接口配置(超详细)
  15. 更改计算机管理员账户用户名和密码,更改电脑的登录用户名为Administrator帐户...
  16. 如何将小车标注在百度地图上并且设置车头方向
  17. 一文读懂遗传算法工作原理(附Python实现)
  18. Windows下LaTex转为Word
  19. Liferay的学习
  20. Linux的bind服务

热门文章

  1. vim 删除行首和行尾空格
  2. FFmpeg进行音频的解码和播放
  3. VM虚拟机去虚拟化教程(三)修改内存品牌和序列号
  4. 关于Catalan(卡特兰)数的理解
  5. 三角形主机linux,受热捧的三角形主机是什么?我来为你解析
  6. Python正则表达式 re
  7. jsch中ChannelShell与ChannelExec区别
  8. Vue 路由懒加载和动态加载
  9. 今天来聊一聊互联网35岁梗,这个行业真的不需要35岁以上从业人员?
  10. Python-pandas:数据合并merge函数用法详解