使用PowerMock模拟静态方法

在最近的博客中,我试图强调使用依赖注入的好处,并表达一种想法,即这种技术的主要好处之一是,通过在类之间提供高度的隔离,它可以使您更轻松地测试代码,并且得出的结论是,许多好的测试等于好的代码。

但是,当您没有依赖项注入并且使用的第三方库包含某个包含静态方法的特定年份的类时,会发生什么? 一种方法是通过在它们周围编写包装器或适配器并在测试过程中提供隔离来隔离这些类。 但是,还有另一种方法:使用PowerMock。 PowerMock是一个模拟框架,可扩展其他模拟框架以提供急需的其他功能。 模仿旧广告:“它刷新了其他模拟框架无法达到的部分”。

该博客介绍了PowerMock模拟静态方法的能力,并提供了一个模拟JDK的ResourceBundle类的示例,众所周知,该类使用ResourceBundle.getBundle(...)来…加载资源束。

与许多其他博客作者和作家一样,我通常会提出一些高度人为的方案来突出问题。 今天有所不同,我只得到了一个使用ResourceBundle的类,称为:UsesResourceBundle:

public class UsesResourceBundle {private static Logger logger = LoggerFactory.getLogger(UsesResourceBundle.class);private ResourceBundle bundle;public String getResourceString(String key) {if (isNull(bundle)) {// Lazy load of the resource bundleLocale locale = getLocale();if (isNotNull(locale)) {this.bundle = ResourceBundle.getBundle("SomeBundleName", locale);} else {handleError();}}return bundle.getString(key);}private boolean isNull(Object obj) {return obj == null;}private Locale getLocale() {return Locale.ENGLISH;}private boolean isNotNull(Object obj) {return obj != null;}private void handleError() {String msg = "Failed to retrieve the locale for this page";logger.error(msg);throw new RuntimeException(msg);}
}

您可以看到有一个方法:getResourceString(…),给定一个键将从包中检索资源字符串。 为了使这项工作更有效率,我懒洋洋地加载了我的资源包,加载后,我调用bundle.getString(key)检索我的资源。 为了测试这一点,我编写了一个PowerMock JUnit测试:

import static org.easymock.EasyMock.expect;
import static org.junit.Assert.assertEquals;
import static org.powermock.api.easymock.PowerMock.mockStatic;
import static org.powermock.api.easymock.PowerMock.replayAll;
import static org.powermock.api.easymock.PowerMock.verifyAll;import java.util.Locale;
import java.util.MissingResourceException;
import java.util.ResourceBundle;import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.api.easymock.annotation.Mock;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;@RunWith(PowerMockRunner.class)
@PrepareForTest(UsesResourceBundle.class)
public class UsesResourceBundleTest {@Mockprivate ResourceBundle bundle;private UsesResourceBundle instance;@Beforepublic void setUp() {instance = new UsesResourceBundle();}@Testpublic final void testGetResourceStringAndSucceed() {mockStatic(ResourceBundle.class);expect(ResourceBundle.getBundle("SomeBundleName", Locale.ENGLISH)).andReturn(bundle);final String key = "DUMMY";final String message = "This is a Message";expect(bundle.getString(key)).andReturn(message);replayAll();String result = instance.getResourceString(key);verifyAll();assertEquals(message, result);}@Test(expected = MissingResourceException.class)public final void testGetResourceStringWithStringMissing() {mockStatic(ResourceBundle.class);expect(ResourceBundle.getBundle("SomeBundleName", Locale.ENGLISH)).andReturn(bundle);final String key = "DUMMY";Exception e = new MissingResourceException(key, key, key);expect(bundle.getString(key)).andThrow(e);replayAll();instance.getResourceString(key);}@Test(expected = MissingResourceException.class)public final void testGetResourceStringWithBundleMissing() {mockStatic(ResourceBundle.class);final String key = "DUMMY";Exception e = new MissingResourceException(key, key, key);expect(ResourceBundle.getBundle("SomeBundleName", Locale.ENGLISH)).andThrow(e);replayAll();instance.getResourceString(key);}}

在上面的代码中,我采取了不寻常的步骤,包括导入语句。 要强调的是,我们使用的是PowerMock的导入静态版本,而不是EasyMock的静态版本。 如果您不小心导入了EasyMock的静态函数,那么整个过程将不起作用。

设置模拟静态调用的测试有四个简单的步骤:

1.使用PowerMock JUnit运行器:

@RunWith(PowerMockRunner.class)

2.声明我们要嘲笑的测试类:

@PrepareForTest(UsesResourceBundle.class)

3.告诉PowerMock包含静态方法的类的名称:

mockStatic(ResourceBundle.class);

4.设置期望值,告诉PowerMock期望对静态方法的调用:

expect(ResourceBundle.getBundle("SomeBundleName", Locale.ENGLISH)).andReturn(bundle);

其余的工作很顺利,您可以为其他标准方法调用设置期望,并告诉PowerMock / EasyMock运行测试,并验证结果:

final String key = "DUMMY";
final String message = "This is a Message";
expect(bundle.getString(key)).andReturn(message);replayAll();
String result = instance.getResourceString(key);
verifyAll();

PowerMock可以做更多的事情,例如模拟构造函数和私有方法调用。 也许以后再说……

参考: 使用PowerMock来模拟我们JCG合作伙伴的 静态方法 调试队长博客上的 Roger。

相关文章 :
  • JUnit 4.9(测试版3)中的规则
  • 使用PowerMock测试对象的内部状态
  • Servlet 3.0异步处理可将服务器吞吐量提高十倍
  • 用Scala测试
  • Java工具:源代码优化和分析
  • Java教程和Android教程列表

翻译自: https://www.javacodegeeks.com/2011/11/mock-static-methods-with-powermock.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/374111.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

多态之向上转型

//向上转型,子类引用指向父类对象 public class UpcastingDemo{ public static void main(String[] args){ Employee enew Employee(); System.out.println(e.grade); e.job(); e.run(); System.out.println("\n"); Manager mnew Manager(…

(转)FPGA异步时序和多时钟模块

http://bbs.ednchina.com/BLOG_ARTICLE_3019907.HTM 第六章 时钟域 有一个有趣的现象,众多数字设计特别是与FPGA设计相关的教科书都特别强调整个设计最好采用唯一的时钟域。换句话说,只有一个独立的网络可以驱动一个设计中所有触发器的时钟端口。虽然…

穆里尼奥:与范加尔风格不同,转变需要时间

据英媒报道,曼联主帅穆里尼奥近日向媒体表示自己很难继续遵循前任主帅范加尔的理念去建立球队,因为他们两人有着完全不同的想法。 穆里尼奥近日在接受BT Sport的采访时表示:“这份工作对于我来说最难的地方便是我与范加尔是非常不同的教练&am…

怎么检测不到我的音频_Linux 上的最佳音频编辑工具推荐 | Linux 中国

在 Linux 上,有很多种音频编辑器可供你选用。不论你是一个专业的音乐制作人,还是只想学学怎么做出超棒的音乐的爱好者,这些强大的音频编辑器都是很有用的工具。-- Ankush Das(作者)在 Linux 上,有很多种音频编辑器可供你选用。不论…

具有GlassFish和一致性的高性能JPA –第3部分

在我的四部分系列的第三部分中,我将解释将Coherence与EclipseLink和GlassFish结合使用的第二种策略。 这就是通过EclipseLink使用Coherence作为二级缓存(L2)的全部内容。 一般的做法 这种方法将Coherence数据网格应用于依赖于无法完全预加载到…

接口使用时注意

interface Service{ void doSome(); //方法的默认修饰符为public abstract } public class InterfaceNote implements Service{ //方法默认的修饰符为 default void doSome(){ System.out.println("做一些服务!"); } public static void main(String…

【Hexo】deploy出错的解决方法

1、ERROR Deployer not found: git 执行npm install hexo-deployer-git --save 2、$ hexo d INFO Deploying: git INFO Clearing .deploy_git folder... INFO Copying files from public folder... fatal: Not a git repository (or any of the parent directories): .git F…

精选30道Java笔试题解答(转)

都是一些非常非常基础的题,是我最近参加各大IT公司笔试后靠记忆记下来的,经过整理献给与我一样参加各大IT校园招聘的同学们,纯考Java基础功底, 老手们就不用进来了,免得笑话我们这些未出校门的孩纸们,但是I…

list取值_Redis中List及quicklist实现-2

上一篇中看了List的使用方式、quicklist中的各个结构体,这一篇来看看quicklist里面的几个核心函数,quicklistCreate函数、quicklistCreateNode函数、quicklistPush函数、quicklistPop函数。接下来我们通过源码看一下quicklist中是如何借鉴STL中deque的这…

通过示例休眠–第1部分(删除孤儿)

所以我想做一系列的冬眠例子,展示冬眠的各种特征。 在第一部分中,我想展示有关删除孤儿功能及其在故事情节中的使用方法。 因此,让我们开始:) 先决条件 : 为了尝试以下示例,您将需要以下提到的JAR文件: …

站长工具--IP地址库

中国最全的IP地址库 转载于:https://www.cnblogs.com/weloveshare/p/5783438.html

String使用注意一

public class StringNote{ public static void main(String[] args){ char[] c{h,e,l,l,o}; String str1new String(c); String str2new String(c); String str3"hello"; //常量池中有 “hello” 字符串,str3和str4分别指向他 String str4"…

Win10手记-IIS部署网站问题解决

最近在自己的Win10电脑上尝试部署ASP.NET网站时出现了问题,经过多方查找定位到IIS为问题来源。 开始之前 先描述下技术环境: 1.Windows 10 PC 2.Windows 自带的IIS 7 3.ASP.NET Web API项目网站 4.VS 2015 问题描述 首先我们为PC安装IIS,按照…

python随机数生成的方法_python生成随机数的方法

一、概述python可以通过random包来产生随机数或者执行一些随机操作。1. random.seed()给定一个数据作为随机数种子,和大多数语言一样,python也可以使用时间来作为随机数种子。import timetime.seed(time.time())12importtimetime.seed(time.time())2. ra…

Java模块化方法–模块,模块,模块

我认为每个人都会同意,编写模块化应用程序和模块化通常是一件好事。 但是,从Java和Scala语言以及各种Java / Scala框架来看,对模块化的支持是怎样的呢? 有很多不同的方法! 让我们看看其中的一些。 “保护”以下是指模块…

CentOS 7 安装记录

由于centos6.4版本有点老,所以换到centos7。 1.安装 CentOS 7.0系统安装配置图解教程 2.linux设置网卡开机启动 实质linux是看一个网卡文件的配置,就是/etc/sysconfig/network-scripts/ifcfg-eth0 (这个文件名看你网卡名称而异,具体你到该目录…

String使用注意二

public class StringNote_1{ public void fun(){ for(int i1;i<100;i){ System.out.print(i""); //此语句很耗时间影响性能 } System.out.println("100"); } public void fun1(){ String text""; for(int i1;i<100;i){ …

python2clock_控制fps的时钟Clock类源码

"""控制fps的时钟Clock类&#xff0c;本程序用来在循环中控制fps。如何在海龟画图中控制fps&#xff1f;这是一个比较重要的问题&#xff0c;否则程序可能有时候快有时候慢。"""import timeimport colorsysfrom turtle import *from random impo…

将mysql的data目录移走方法

如移动到"/home/mysql/data"&#xff0c;我的mysql是装在/usr/local/mysql下的 1. 将/usr/local/mysql/data移动到/home/mysql/data mv /usr/local/mysql/data /home/mysql/data 2. 修改启动文件 vi /usr/local/mysql/support-files/mysql.server 修改如下行&#xf…

Integer注意_享元设计模式

public class IntegerNote{ public static void main(String[] args){ Integer d1100; Integer d2100; System.out.println(d1d2); //true Integer d3129; Integer d4129; System.out.println(d3d4); //false } } /* 究其原因则涉及到java设计中的一个设计模式&am…