2013-05-03 87 views
3

最近我寫了一些對象,其中一個方法的行爲有時包含在某些條件下調用另一個方法的方法。爲了測試這個,我一直在嘲笑對象自己調用的方法,因爲它可以更容易地覆蓋代碼中的每個分支,而無需組合爆炸。這通常被認爲是不好的做法。但是,這裏有一個例子幾乎完全反映了我現在正在處理的一段代碼(用CoffeeScript編寫,但這個哲學問題在其他語言中也出現過了)。被測對象的模擬方法

class UserDataFetcher 
    constructor: (@dataSource) -> 

    fetchUsernameAsync: -> 
    # ... snip ... Hits API and raises any errors 

    fetchUserCommentsAsync: -> 
    # ... snip ... Hits API and raises any errors 

    fetchUsernameAndUserCommentsAsync: -> 
    # ... snip ... Calls each of the above in order and handles errors specially 

這很簡單。 fetchUsernameAsyncfetchUserCommentsAsync每個與給定的@dataSource交互以獲取數據。然後我們有fetchUsernameAndUserCommentsAsync這實質上是一個組合的方法調用其他兩個並以某種方式處理它們;在這個例子中,它可能想重新產生由fetchUsernameAsync產生的任何錯誤,但是吞下fetchUserCommentsAsync引發的任何錯誤。

測試前兩種方法的行爲是微不足道的;我嘲笑了他們各自對@dataSource的調用,並斷言他們以正確的格式返回數據或允許引發任何錯誤。測試最後一種方法的行爲就是我的困境。

它仍然是一個簡單的方法,具有最少的分支邏輯,並通過傳遞消息來委託大部分工作。通常,我會通過嘲笑其「協作者」來測試其行爲,並對某些正在傳遞的消息進行斷言,並以適當的格式返回數據或正確地失敗。但區別在於它只有一個「合作者」,this。我會嘲笑被測對象的一些方法,這被認爲是不好的做法。

很明顯,解決這個問題的方法是將此方法移到不同的對象;它將是一個只有一個方法和幾乎完全相同的機制的對象,它可以讓我在不違反「不要模擬被測對象」方法規則的情況下嘲笑其協作者。它可能會有一個荒謬的名字,比如UsernameAndCommentsFetcher,我會從一個小班走到兩個微小的,幾乎微觀的班。小的類很好,但是這個粒度級可能有點矯枉過正,在這種情況下只會滿足「不要模擬被測對象的方法」規則。

這是一個堅實的規則還是有這種情況下,這種情況下,彎曲規則是合理的?

(注:我知道這是類似這個問題,但我認爲這個例子是不夠的不同,值得重新審視:As a "mockist" TDD practitioner, should I mock other methods in the same class as the method under test?

回答

1

編程很少規則是100%固體。

但是在這種情況下,您是否可以將fetchUsernameAsync和fetchUserCommentsAsync的模擬設置代碼提取到安裝方法中,然後在fetchUsernameAndUserCommentsAsync中調用這兩個代碼?例如(在RSpec中的語法):

specify "fetchUsernameAsync" do 
    setup_username_mock 
    expect(...).to eq ... 
end 

specify "fetchCommentsAsync" do 
    setup_comments_mock 
    expect(...).to eq ... 
end 

specify "fetchUsernameAndCommentsAsync" do 
    setup_username_mock 
    setup_comments_mock 
    expect(...).to eq ... 
end 

會有不需要的fetchUsernameAndCommentsAsync測試覆蓋已經由先前的規格覆蓋了所有的路徑。

相關問題