powermock模拟对象_使用PowerMock测试对象的内部状态
powermock模擬對象
大多數(shù)單元測試都集中于測試對象的行為以證明其有效。 這可以通過編寫一個JUnit測試來實現(xiàn),該測試調(diào)用對象的公共方法,然后測試這些調(diào)用的返回值是否與先前定義的一組期望值匹配。 這是一種非常常見且成功的技術(shù)。 但是,不應(yīng)忘記對象也顯示狀態(tài)。 由于它是隱藏的,因此經(jīng)常被忽略。我于1995年夏季首次閱讀Grady Booch的1994年的《 面向?qū)ο蟮姆治龊驮O(shè)計 》一書,它通過以下方式定義了對象的狀態(tài):
對象的狀態(tài)包含對象的所有(通常是靜態(tài))屬性以及這些屬性中每個屬性的當(dāng)前(通常是動態(tài))值。
他使用自動售貨機(jī)示例定義了靜態(tài)和動態(tài)狀態(tài)之間的差異。 靜態(tài)狀態(tài)是通過機(jī)器始終準(zhǔn)備好拿錢的方式表現(xiàn)出來的,而動態(tài)狀態(tài)是在任何給定實例中獲得的錢數(shù)。
我懷疑在這一點上,您會正確地辯稱,明確的行為測試確實會測試對象的狀態(tài),這是因為給定的方法調(diào)用返回了正確的結(jié)果,并且要獲得正確的結(jié)果,對象的狀態(tài)也必須是是的...我會同意的。 但是,在極少數(shù)情況下,經(jīng)典行為測試不適用。 當(dāng)公共方法調(diào)用沒有輸出并且對對象不執(zhí)行任何操作(更改其狀態(tài))時,會發(fā)生這種情況。 一個示例是返回void的方法或構(gòu)造函數(shù)。 例如,給定一個具有以下簽名的方法:
public void init();…如何確保其完成工作? 事實證明,有幾種方法可以用來實現(xiàn)這一目標(biāo)……
- 向您的類中添加許多getter方法。 這不是一個特別好的主意,因為您只是在松開后門的封裝。
- 放松封裝:將私有實例變量打包為私有。 一個非常有爭議的事情。 您可能會務(wù)實地認(rèn)為,經(jīng)過良好測試,正確和可靠的代碼可能比高度封裝更好,但是我在這里不太確定。 這可能是一個短期修復(fù),但將來可能會導(dǎo)致各種問題,因此應(yīng)該有一種編寫經(jīng)過良好測試,正確和可靠的代碼的方式,其中不包括破壞對象的封裝
- 編寫一些使用反射來訪問對象內(nèi)部狀態(tài)的代碼。 這是迄今為止最好的主意。 不利的一面是,這需要付出相當(dāng)大的努力,并且需要一定數(shù)量的編程能力。
- 使用PowerMock的Whitebox測試課程為您完成艱苦的工作。
以下完全人為設(shè)計的場景演示了PowerMock的Whitebox類的用法。 它需要一個非常簡單的AnchorTag <a>類,該類將在測試輸入URL字符串有效之后構(gòu)建一個錨標(biāo)記。
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驗證測試是使用正則表達(dá)式和Java Pattern對象完成的。 使用Whitebox類將確保正確配置模式對象,并且我們的AnchorTag處于正確的狀態(tài)。 下面的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());}該測試的關(guān)鍵是該行:
Pattern result = Whitebox.<pattern> getInternalState(instance, "pattern");…使用反射返回Pattern對象的私有實例變量。 一旦訪問了該對象,我們就可以簡單地通過調(diào)用以下命令詢問它是否已正確初始化:
assertEquals("^([a-zA-Z0-9]([a-zA-Z0-9\\-]{0,61}[a-zA-Z0-9])?\\.)+[a-zA-Z]{2,6}$", result.pattern());總而言之,我建議僅在無法將簡單的經(jīng)典JUnit測試用于行為測試時,才應(yīng)使用PowerMock顯式測試對象的內(nèi)部狀態(tài)。 話雖如此,它是工具箱中的另一個工具,可以幫助您編寫更好的代碼。
參考:來自JCG合作伙伴的 PowerMock測試對象的內(nèi)部狀態(tài) 調(diào)試隊長博客上的 Roger。
相關(guān)文章 :- JUnit 4.9(測試版3)中的規(guī)則
- Servlet 3.0異步處理可將服務(wù)器吞吐量提高十倍
- 用Scala測試
- Java工具:源代碼優(yōu)化和分析
- Java教程和Android教程列表
翻譯自: https://www.javacodegeeks.com/2011/10/testing-objects-internal-state-with.html
powermock模擬對象
總結(jié)
以上是生活随笔為你收集整理的powermock模拟对象_使用PowerMock测试对象的内部状态的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
 
                            
                        - 上一篇: linux查看编码格式命令(linux
- 下一篇: InterServer vs Blueh
