使用PowerMock測試對象的內部狀態

大多數單元測試都集中于測試對象的行為以證明其有效。 這可以通過編寫一個JUnit測試來實現,該測試調用對象的公共方法,然后測試這些調用的返回值是否與先前定義的一組期望值匹配。 這是一種非常常見且成功的技術。 但是,不應忘記對象也顯示狀態。 由于它是隱藏的,因此經常被忽略。

我于1995年夏季首次閱讀Grady Booch的1994年的《 面向對象的分析和設計 》一書,它通過以下方式定義了對象的狀態:

對象的狀態包含對象的所有(通常是靜態)屬性以及這些屬性中每個屬性的當前(通常是動態)值。

他使用自動售貨機示例定義了靜態和動態狀態之間的差異。 靜態狀態是通過機器始終準備好取錢的方式表現出來的,而動態狀態是在任何給定實例中獲得多少錢的狀態。

我懷疑在這一點上,您會正確地辯稱,顯式行為測試確實會測試對象的狀態,這是因為給定的方法調用返回了正確的結果,并且為了獲得正確的結果,對象的狀態也必須是是的...我會同意的。 但是,在極少數情況下,經典行為測試不適用。 當公共方法調用沒有輸出并且對對象不執行任何操作(更改其狀態)時,會發生這種情況。 一個示例是返回void的方法或構造函數。 例如,給定一個具有以下簽名的方法:

public void init();

…您如何確保已完成工作? 事實證明,有幾種方法可以用來實現這一目標……

  • 在您的類中添加許多getter方法。 這并不是一個特別好的主意,因為您只是在松開后門的封裝。
  • 放松封裝:將私有實例變量打包為私有。 一個非常有爭議的事情。 您可能會務實地認為,經過良好測試,正確和可靠的代碼可能比具有高度的封裝更好,但是我在這里不太確定。 這可能是一個短期修復,但將來可能會導致各種問題,因此應該有一種編寫經過良好測試,正確和可靠的代碼的方式,其中不包括破壞對象的封裝
  • 編寫一些使用反射來訪問對象內部狀態的代碼。 這是迄今為止最好的主意。 不利的一面是,這需要付出相當大的努力,并且需要一定數量的編程能力。
  • 使用PowerMock的Whitebox測試課程為您完成艱苦的工作。

以下完全人為設計的方案演示了PowerMock的Whitebox類的用法。 它需要一個非常簡單的AnchorTag <a>類,該類將在測試輸入URL字符串有效之后構建一個錨標記。

public class AnchorTag {private static final Logger logger = LoggerFactory.getLogger(AnchorTag.class);/** Use the regex to figure out if the argument is a URL */private final Pattern pattern = Pattern.compile("^([a-zA-Z0-9]([a-zA-Z0-9\\-]{0,61}[a-zA-Z0-9])?\\.)+[a-zA-Z]{2,6}$");/*** A public method that uses the private method*/public String getTag(String url, String description) {validate(url, description);String anchor = createNewTag(url, description);logger.info("This is the new tag: " + anchor);return "The tag is okay";}/*** A private method that's used internally, but is complex enough to require testing in its own right*/private void validate(String url, String description) {Matcher m = pattern.matcher(url);if (!m.matches()) {throw new IllegalArgumentException();}}private String createNewTag(String url, String description) {return "<a href=\"" + url + "\">" + description + "</a>";}
}

URL驗證測試是使用正則表達式和Java Pattern對象完成的。 使用Whitebox類將確保正確配置模式對象,并且我們的AnchorTag處于正確的狀態。 下面的JUnit測試證明了這一點:

/*** Works for private instance vars. Does not work for static vars.*/@Testpublic void accessPrivateInstanceVarTest() throws Exception {Pattern result = Whitebox.<pattern> getInternalState(instance, "pattern");logger.info("Broke encapsulation to get hold of state: " + result.pattern());assertEquals("^([a-zA-Z0-9]([a-zA-Z0-9\\-]{0,61}[a-zA-Z0-9])?\\.)+[a-zA-Z]{2,6}$", result.pattern());}

該測試的關鍵是:

Pattern result = Whitebox.<pattern> getInternalState(instance, "pattern");

…使用反射返回Pattern對象的私有實例變量。 一旦可以訪問該對象,我們只需調用它即可詢問它是否已正確初始化:

assertEquals("^([a-zA-Z0-9]([a-zA-Z0-9\\-]{0,61}[a-zA-Z0-9])?\\.)+[a-zA-Z]{2,6}$", result.pattern());

總而言之,我建議僅在無法使用簡單直接的經典JUnit測試進行行為測試時,才應使用PowerMock顯式測試對象的內部狀態。 話雖如此,它是工具箱中的另一個工具,可以幫助您編寫更好的代碼。

參考:來自JCG合作伙伴的 PowerMock測試對象的內部狀態 調試隊長博客上的 Roger。

相關文章 :
  • JUnit 4.9(測試版3)中的規則
  • Servlet 3.0異步處理可將服務器吞吐量提高十倍
  • 用Scala測試
  • Java工具:源代碼優化和分析
  • Java教程和Android教程列表

翻譯自: https://www.javacodegeeks.com/2011/10/testing-objects-internal-state-with.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:
http://www.pswp.cn/news/374144.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/374144.shtml
英文地址,請注明出處:http://en.pswp.cn/news/374144.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

布局

1&#xff09;ul li 把ul寬度設置大一點&#xff0c;然后overflowhidden;&#xff08;最好不要嵌套使用&#xff0c;原因看清除浮動方法&#xff09;&#xff0c;然后外面必須有包裹的div殼&#xff0c;div殼的寬度就按設計稿來&#xff0c;這樣就避免了需要給最后一個li設置m…

10個職場故事,讓人不得不看

1、強盜師徒 有一次&#xff0c;一個老強盜帶著徒弟去搶劫銀行&#xff0c;被警方追捕。兩人狂逃&#xff0c;差點兒連褲子都跑掉了。好不容易甩掉了警察&#xff0c;兩人上氣不接下氣&#xff0c;癱倒在地上。 良久&#xff0c;驚魂稍定&#xff0c;徒弟說:“師父啊師父&#…

NXP UWB NCJ29D5開發(一)環境搭建

1、從NXP的共享賬號下載資料 共享賬號需要找對接的NXP人員拿到&#xff0c;他會把資料分享到這個賬號&#xff0c;在這個賬號里面可以下載 進入nxp官網&#xff0c;登錄后點擊my nxp&#xff0c;選擇Software Licensing and Support 進入后接著選擇View accounts 進入后選擇…

西瓜創客python編程進階收費_西瓜創客和編程貓有什么不同?哪個更值得報名?...

看情況來決定即可&#xff0c;在課程內容上其實出入我覺得不是很大&#xff0c;重點是教學服務、師資、授課模式等&#xff0c;單純我自己的角度來說&#xff0c;我個人偏向于西瓜創客多一點&#xff0c;他們家的課程更具有趣味性&#xff0c;游戲化教學&#xff0c;融入卡通人…

Stack的三種含義

作者&#xff1a;阮一峰 學習編程的時候&#xff0c;經常會看到stack這個詞&#xff0c;它的中文名字叫做”棧”。 理解這個概念&#xff0c;對于理解程序的運行至關重要。容易混淆的是&#xff0c;這個詞其實有三種含義&#xff0c;適用于不同的場合&#xff0c;必須加以區分。…

NXP UWB NCJ29D5開發(二)BlinkyLed例程

路徑為UWB\NCJ29D5\NCJ29D5_CAS_Examples_v1.4\onic\BlinkyLed\toolsupport\keil 例程怎么來的可以看看上一篇NXP UWB NCJ29D5開發&#xff08;一&#xff09;環境搭建 1、 //系統選擇外部晶振&#xff0c;時鐘頻率為55.2Mhz phscaAppHal_Init(PHSCA_APPHAL_XO_CLOCK_SOURCE_…

你要看透的56條人生哲理

當你躊躇不前、站在人生十字路口時候&#xff0c;這56條哲理或許能助你一臂之力&#xff01;      1&#xff0e;拿得起&#xff0c;放得下      我們每個人都有很多“寶貝”&#xff0c;但你不可能什么都得到&#xff0c;在某些時候一定要學會拿得起&#xff0c;放得下…

使用Spring和Java泛型簡化數據訪問層

1.概述 本文將著重于通過對系統中的所有實體使用單個通用的數據訪問對象來簡化DAO層 &#xff0c;這將導致優雅的數據訪問 &#xff0c;而不會造成不必要的混亂或冗長。 2. Hibernate和JPA DAO 大多數生產代碼庫都有某種DAO層。 通常&#xff0c;實現范圍從沒有抽象基類的多個…

強肝保肝養肝4大食物

“強肝的食物,保肝的食物有哪些,養肝的食物有哪些”如果您對這些食物不了解不明白。那就看看專家為您推薦的四款強肝保肝養肝的食物。荔枝&#xff08;供圖/華蓋&#xff09;一、是荔枝&#xff0c;荔枝可以保肝&#xff0c;對肝有好處根據《本草綱目》記載荔枝有強肝健胰的效果…

如何查看注解實現_該怎么運用注解呢?Java團隊元老有話說

來源 | 異步 15講能學好誕生24年的JAVA嗎&#xff1f;你當然會感到懷疑&#xff0c;眾所周知&#xff0c;在技術向的IT論壇上&#xff0c;“如何在十天之內快速掌握好Java&#xff1f;”這類問題&#xff0c;往往會招來嘲笑。來源于知乎但在當下&#xff0c;5分鐘能看完一部電影…

NXP S32K144開發(一)環境搭建和新建工程

1、首先需要安裝S32 Design Studio for ARM&#xff0c;在NXP官網可以搜索到&#xff0c;這玩意也是基于eclipse的 安裝好后就可以打開了。 2、新建工程 過程可以參考NXP官網&#xff1a; https://www.nxp.com/document/guide/get-started-with-the-s32k144evb:NGS-S32K144E…

首先記錄異常的根本原因

Logback日志庫的0.9.30版本帶來了一個很棒的新功能&#xff1a;從根&#xff08;最內部&#xff09;異常而不是最外部異常開始記錄堆棧跟蹤。 當然&#xff0c;我的興奮與我貢獻了此功能無關。 用塞西爾德米勒&#xff08;Cecil B. de Mille&#xff09; 的話來解釋&#xff1a…

成功醒言

成功醒言 C01 只有敢犯錯誤的人才能成事&#xff1b; 只有不犯同樣錯誤的人才能成大事。 C02 固執≠執著&#xff1b; 幻想≠希望。 固執是無目標的執著&#xff1b; 執著是有目標的固執。 幻想是無法兌現的希望&#xff1b; 希望是有望實現的幻想。 固執地執著幻想&#xf…

Android 中的 Service 全面總結

1、Service的種類 按運行地點分類&#xff1a; 類別區別 優點缺點 應用本地服務&#xff08;Local&#xff09;該服務依附在主進程上&#xff0c; 服務依附在主進程上而不是獨立的進程&#xff0c;這樣在一定程度上節約了資源&#xff0c;另外Local服務因為是在同一進程因此不…

python基礎學習1-三元表達式和lambda表達式

#!/usr/bin/env python # -*- coding:utf-8 -*- 三元運算 if else 的簡寫name "alex" if 11 else "SB" #如果條件成立 賦alex 否則 賦SB print(name)#--------------lambda表達式 f2 lambda a1,a2:a1a2100 #等價 下邊函數定義 def f1(a1,a2): return …

怎么讓存儲過程通用化_怎么做分布式存儲的面試?

cholerae 大神已經做了詳細回答&#xff0c;http://zenlife.tk/interview-for-distributed-storage.md寫于幾年前&#xff0c;內容有點稚嫩&#xff0c;WAL辨識度很高, 其他問題一般.CAP不會再問了&#xff0c;專業的存儲文獻中很少(幾乎不)提及CAP或PACELC, 這個詞用于市場和銷…

Java EE中的配置管理

我嘗試配置管理在云計算中具有很多相關性 爭論 較早。 實際上&#xff0c;我大膽地宣稱配置管理是任何認真嘗試從軟件中節省幾美元的基石。 那么什么是配置管理及其主要目標&#xff1f; 在不使事情變得過于復雜的情況下&#xff0c;我認為接下來的兩個目標與事實相差不遠。 以…

十年總結,一個JAVA人的十年人生路

十年總結-開篇&#xff1a;歇一歇&#xff0c;才能走的更遠經常見壇子里有人問&#xff0c;學習java該如何入手&#xff0c;或者是該學java還是學XX語言。我一直覺得&#xff0c;編程跟語言關系不大&#xff0c;重點是要有解決問題的思路。學習一門語言&#xff0c;其實只是尋求…

(四)Qt實現自定義模型基于QAbstractTableModel (一般)

Qt實現自定義模型基于QAbstractTableModel 兩個例子 例子1代碼 Main.cpp #include <QtGui>#include "currencymodel.h"int main(int argc, char *argv[]) {QApplication app(argc, argv);//數據源QMap<QString, double> currencyMap;currencyMap.insert(…

pt-query-digest使用介紹【轉】

本文來自&#xff1a;http://isadba.com/?p651 一、pt-query-digest參數介紹. pt-query-digest --useranemometer --passwordanemometerpass --review h192.168.11.28,Dslow_query_log,tglobal_query_review \--history h192.168.11.28,Dslow_query_log,tglobal_query_re…