簡體   English   中英

如何對此進行單元測試(使用模擬還是經典的單元測試?)

[英]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,則可以創建它們。

在我的日常工作中,我嘗試先編寫單元測試,然后再設計功能,因為它有助於設計易於使用/測試的界面。

http://en.wikipedia.org/wiki/Test-driven_development

我認為模擬是可以的。

另一方面:JUnit測試不僅是簡單的測試,而且還會推動設計。

如果發現難以編寫測試用例,例如構造函數采用了復雜的參數,則可以重新考慮設計。

順便說一句,我認為方法getPreviousName()是沒有必要的, getPreviousEntry()就足夠了。

暫無
暫無

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

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