使用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.pswp.cn/news/374111.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/374111.shtml
英文地址,請注明出處:http://en.pswp.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…