[英]How to Unit Test this (use mocks, or classical unit test?)
我需要為以下方法(簡化)編寫一個JUnit測試:
/** Return name of previous entry or name of given entry if no previous entry. */
public String getPreviousName(TreeEntry entry) {
if (entry.getPrevious() != null) {
return entry.getPrevious().getName();
} else {
return entry.getName();
}
}
我只是不知道該如何測試。 我可以
a)使用Mocks模擬出參數及其先前的條目,或
b)創建一個真實的TreeEntry及其真實的上一個條目
使用模擬的問題是,我需要在測試案例中說出實際實現需要使用哪種方法,例如,在這里我說正確的名稱是通過TreeEntry的getPrevious()然后通過先前條目的getName()獲得的。 (不考慮if null的情況,因為這基本上不是問題):
TreeEntry mockEntry = mock(TreeEntry.class);
TreeEntry mockPreviousEntry = mock(TreeEntry.class);
when(mockEntry.getPrevious()).thenReturn(mockPreviousEntry);
when(mockPreviousEntry.getName()).thenReturn("testName");
assertEquals("testName", classUnderTest.getPreviousName(mockEntry));
但是,例如,實現者也可以這樣實現:
return NameService.getName(entry.getPrevious());
測試無關緊要。
但是,如果我使用沒有模擬的經典單元測試,則會遇到另一個問題。 TreeEntry的構造函數非常復雜。 它有5個需要有效對象的參數。 因此,創建類似以下內容非常復雜:
TreeEntry entry = new TreeEntry(...);
TreeEntry previousEntry = new TreeEntry(...);
entry.setPrevious(previousEntry);
previousEntry.setName("testName");
assertEquals("testName", classUnderTest.getPreviousName(entry));
該代碼將比這更長,因為構造函數采用了復雜的參數。 另一件事是,構造函數訪問文件系統以從那里加載其內容,因此這增加了單元測試的速度。
使用經典方法,它還將測試與TreeEntry的實現更多地聯系在一起。 因為如果在TreeEntry中使用構造函數或上一個條目的設置進行了某些更改,則也需要在測試中進行更改。 如果忘記了它,即使被測類不是TreeEntry,也會導致測試失敗。
您說什么是對此進行單元測試的正確方法?
我個人傾向於更喜歡嘲笑的方法。 可以肯定地說,在一個測試用例中,我已經指定了被測試類的協作者,因為在某種程度上它還屬於設計而非實現?
最好的問候,亞歷克斯
我認為您的TreeEntry
方法看起來不錯(並且我同意,如果TreeEntry
像您所說的那樣復雜,則不應將它們混入這些測試中(但我希望您在其他地方進行TreeEntry
測試))。 如果您正在編寫許多類似這樣的測試,則應考慮采用一些Builder模式(如果有耐心,可以使用流利的語法),以便可以構建類似以下的模擬程序:
BuildANew.TreeEntry().WithPreviousEntryName("testName");
或者,您可以創建一個ITreeEntry
接口,並根據ITreeEntry
接口編寫樹操作代碼,並創建一個簡單的存根實現以傳遞到測試中,這樣您就無需弄亂模擬設置代碼了。 或者,對於更簡潔的方法,請創建界面並對其進行模擬。
我認為您最好的選擇是從TreeEntry中提取接口,並在測試代碼中使用s基本存根實現它,然后對此進行測試。
如果您只想測試
public String getPreviousName(TreeEntry entry)
方法我會嘲笑它,因為您只是對該方法進行單元測試。 保持單元測試快是一個好習慣。
但是,如果您有興趣測試整個文件訪問權限和創建TreeEntry,則可以創建它們。
在我的日常工作中,我嘗試先編寫單元測試,然后再設計功能,因為它有助於設計易於使用/測試的界面。
我認為模擬是可以的。
另一方面:JUnit測試不僅是簡單的測試,而且還會推動設計。
如果發現難以編寫測試用例,例如構造函數采用了復雜的參數,則可以重新考慮設計。
順便說一句,我認為方法getPreviousName()
是沒有必要的, getPreviousEntry()
就足夠了。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.