簡體   English   中英

何時在單元測試中繞過封裝是否合適?

[英]When is it appropriate to bypass encapsulation in unit tests?

我最近開始意識到powermock的Whitebox功能。 (總之,它允許您直接測試私有方法或直接從單元測試修改私有成員 - 同時保持私有!)

我知道除了可見方法之外,還有一些思想框架在單元測試之后不屑一顧,但是有時它只是想要一個簡單的測試來確保深層輔助方法正在做它應該做的事情......沒有經歷可能是巨大的開銷來准備父方法過濾到你的方法所需的參數和模擬......然后你只需要做魔法來提取內部方法的結果。 簡而言之,有時測試這些內部方法需要最復雜且難以遵循的單元測試。 (而且,我們公司的政策是100%的單位測試覆蓋率。 這些方法必須經過測試!

我知道一種方法更改方法訪問器以允許單元測試(例如,從private更改為protected ,但powermock Whitebox允許直接測試而不更改源代碼。

不過,媽媽總是說,“只因為你可以,並不意味着你應該這樣做。”

是否適合測試這樣的內部方法? 如果是這樣,我應該使用的經驗法則是什么?

讓我們首先承認這是一場部分宗教辯論

我的觀點是,測試private方法是您應該經常避免的,但也有例外。

我為什么不測試private方法?

因為您正在測試您的應用程序是否有效,不一定是如何工作的。 private方法不是您的程序公開的API的一部分,它本質上是一個實現細節。

通過封裝並仍在測試它來解決限制的一個常見論點是它可能會破壞測試該特定實現的測試。

在“正常”測試中,我們測試public方法,因為它們構成了我們的程序:如果我們知道所有公共API工作,那么我們知道程序將起作用。 如果您的應用程序結構合理,那么您將擁有多個API層,這些API層不斷將測試細化為更小的單元,以便您可以清楚地了解某些地方可能出現的問題。

關於private方法的事情是,它們總是會在某個時候通過public方法被調用,這將被測試。 private方法是被測單元的實現細節,因此不應單獨測試。

這個輔助方法不受API約束,因此不能保證它的效果保持不變; 在不調整整體功能的情況下更改實現細節現在將破壞您對該方法的測試。 因此,即使您的程序仍然完美無缺,但現在您的測試已經破損。 這些測試是不穩定的:一個不改變你的功能的重構仍然會導致你必須刪除單元測試,因為它們不再相關(這本身很危險,因為你必須非常確定測試實際上多余的)。

我為什么要測試private方法?

只有少數東西是黑白的,這不是其中之一。 我相信新代碼不應該測試private方法,但這是我區別的地方: 新代碼

如果繼承遺留代碼庫,那么架構可能不是很漂亮。 您可能需要跳過箍,整個代碼流可能會更好。

所以你要做的第一件事是編寫一些單元測試,保證在你打破功能時告訴你。 到目前為止,我們現在可以進入實際的重構過程。 讓我們從這個500行private方法開始吧?

記住以前的評論時,您現在必須查看代碼流並查看哪些public方法使用該private方法,並在進行更改時密切關注它們。

為了易於使用,我會在這里編寫測試,只測試該private方法與你的應用程序其余部分的合同:只要你的方法的結果沒有區別,你知道它贏了“ t影響任何其他遺留方法。 有了這些知識,您現在可以輕松地重構該方法中的所有內容。 什么東西壞了; 您可以立即使用輔助方法,而不必使用公共API方法。

請記住,我只會為大型重構操作執行此操作:這些是首先進行的臨時測試,“實現細節”實際上是500行代碼:這是一個有很多細節的細節。

我該如何測試private方法?

這里有一些關於如何使這些可測試的選項:

反射

我相信這就是WhiteBox使用的。 雖然它引起了一些人的注意:沒有靜態類型(更改方法名稱意味着破壞測試), 它很昂貴 ,使用反射的代碼往往難以閱讀。

PrivateObject

我沒有看過確切的實現,但我很確定這會在幕后使用反射。 基本上它通過方便的界面提供反射方法。 我沒有看到它用得太多(部分是因為我會使用反射作為絕對的最后手段)但它就在那里。

MSDN

萃取

這將是我的第一個方法:這個輔助方法是否足夠重要,使其獨立? 你可能會對此說“是”,因為顯然它已經非常重要,你想要對它進行明確的測試。

上市

最明顯的選擇:簡單地public 它遵循與提取相同的想法:“它能獨立存在嗎?”。 這里的區別在於你仍然認為這是當前類的一部分,你只是提升它的訪問權限,而將它提取到另一個類也表明你所說的不僅僅是一個輔助方法。

內部

此選項采用中間路徑:如果我將其設置為內部(C#上下文)並使用[InternalsVisibleTo]屬性,則可以將其設置為internal同時為測試程序集提供測試它的可能性(並使其遠離公共API) 。

這帶來了人們只將其視為實現細節並在破壞測試時更改實現(這是特定實現)的風險。

此外,這還增加了應用程序和測試之間的耦合。


所有人都認為這取決於你自己的偏好:測試private方法有幾種選擇,雙方都有一些爭論。 就個人而言,我會遠離測試此類實現細節的麻煩,而是看看我能做些什么來改進我的架構。 機會是問題將以這種方式解決。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM