使用PowerMock模拟静态方法
但是,當(dāng)您沒(méi)有依賴項(xiàng)注入并且使用的第三方庫(kù)包含某個(gè)包含靜態(tài)方法的特定年份的類時(shí),會(huì)發(fā)生什么? 一種方法是通過(guò)在它們周圍編寫包裝器或適配器并在測(cè)試過(guò)程中提供隔離來(lái)隔離這些類。 但是,還有另一種方法:使用PowerMock。 PowerMock是一個(gè)模擬框架,可擴(kuò)展其他模擬框架以提供急需的其他功能。 模仿舊廣告:“它刷新了其他模擬框架無(wú)法達(dá)到的部分”。
該博客介紹了PowerMock模擬靜態(tài)方法的能力,并提供了一個(gè)模擬JDK的ResourceBundle類的示例,眾所周知,該類使用ResourceBundle.getBundle(...)來(lái)…加載資源束。
與許多其他博客作者和作家一樣,我通常會(huì)提出一些高度人為的方案來(lái)突出問(wèn)題。 今天有所不同,我只得到了一個(gè)使用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);} }您可以看到有一個(gè)方法:getResourceString(…),給定一個(gè)鍵將從包中檢索資源字符串。 為了使這項(xiàng)工作更有效率,我懶洋洋地加載了我的資源包,加載后,我調(diào)用bundle.getString(key)檢索我的資源。 為了測(cè)試這一點(diǎn),我編寫了一個(gè)PowerMock JUnit測(cè)試:
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);}}在上面的代碼中,我采取了不尋常的步驟,包括導(dǎo)入語(yǔ)句。 要強(qiáng)調(diào)的是,我們使用的是PowerMock的導(dǎo)入靜態(tài)版本,而不是EasyMock的靜態(tài)版本。 如果您不小心導(dǎo)入了EasyMock的靜態(tài)函數(shù),那么整個(gè)過(guò)程將不起作用。
設(shè)置模擬靜態(tài)調(diào)用的測(cè)試有四個(gè)簡(jiǎn)單的步驟:
1.使用PowerMock JUnit運(yùn)行器:
@RunWith(PowerMockRunner.class)2.聲明我們要嘲笑的測(cè)試類:
@PrepareForTest(UsesResourceBundle.class)3.告訴PowerMock包含靜態(tài)方法的類的名稱:
mockStatic(ResourceBundle.class);4.設(shè)置期望值,告訴PowerMock期望對(duì)靜態(tài)方法的調(diào)用:
expect(ResourceBundle.getBundle("SomeBundleName", Locale.ENGLISH)).andReturn(bundle);其余的工作很順利,您可以為其他標(biāo)準(zhǔn)方法調(diào)用設(shè)置期望,并告訴PowerMock / EasyMock運(yùn)行測(cè)試,并驗(yàn)證結(jié)果:
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可以做更多的事情,例如模擬構(gòu)造函數(shù)和私有方法調(diào)用。 也許以后再說(shuō)……
參考: 使用PowerMock來(lái)模擬我們JCG合作伙伴的 靜態(tài)方法 調(diào)試隊(duì)長(zhǎng)博客上的 Roger。
相關(guān)文章 :- JUnit 4.9(測(cè)試版3)中的規(guī)則
- 使用PowerMock測(cè)試對(duì)象的內(nèi)部狀態(tài)
- Servlet 3.0異步處理可將服務(wù)器吞吐量提高十倍
- 用Scala測(cè)試
- Java工具:源代碼優(yōu)化和分析
- Java教程和Android教程列表
翻譯自: https://www.javacodegeeks.com/2011/11/mock-static-methods-with-powermock.html
總結(jié)
以上是生活随笔為你收集整理的使用PowerMock模拟静态方法的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 邮政理财宝利息怎么算?
- 下一篇: 余额宝利息比银行高吗?