2011-12-11 59 views
3

我被招聘爲SW開發,我試圖進入單元測試與RSPEC和紅寶石RR,但有一個很難決定在特定的策略,主要是因爲我是指定將單元測試寫入已寫入的代碼。Ruby單元測試技術,懲戒和打樁

考慮下面的代碼這是一個大方法的一部分被稱爲方法一:

if (["5234541252", "6236253223"].include?(self.id)) 
    self.DoCheck 
    logs.add 'Doing check', "id = #{self.id}" 
    return 
    end 

的方法,這部分的相關單元測試會一直是這樣的:

"should do check only if id = 5234541252 or 6236253223"

但我遇到幾個問題,基本上涉及最佳實踐,例如:

如何檢查DoCheck已經使用RR和RSPEC從「method1」中調用?

我使用dont_allow(對象).DoCheck嘗試,但它不會工作。

describe :do_route do 
    it "should do check only if id = 5234541252 or 6236253223" do 
    user = Factory(:User) 
    user.id = "5234541252" 

    dont_allow(user).DoCheck 
    user.method1 
end 

如果「DoCheck」被調用或沒有被調用,還有其他方式可以得出結論嗎?

+1

這是「大方法的一部分」,這是一個巨大的紅旗。爲了更好,更簡單,更有效的測試,需要對代碼進行重構。此外,我懷疑許多其他問題,如使用InitialCaps的方法名稱所證明的。 –

+0

我完全同意,但不幸的是,重構代碼目前無法解決問題。 –

+0

什麼?如果他們不願意改進代碼,他們希望進行單元測試。 –

回答

0

你可以用你的對象「部分嘲諷」技術下的測試。這意味着您需要設置user.method1發送DoCheck消息到user的期望值。 RSpec可以使用should_receive()方法設置此預期。如果期望不會被滿足,測試將失敗。

試試下面的代碼:

describe :do_route do 
    it "should do check if id = 5234541252 or 6236253223" do 
    user = Factory(:User) 
    user.id = "5234541252" 

    user.should_receive(:DoCheck) # set expectation that DoCheck will be called 

    user.method1 # execute 
    end 
end 

隨着RR這種預期可能是這樣的:

describe :do_route do 
    it "should do check if id = 5234541252 or 6236253223" do 
    user = Factory(:User) 
    user.id = "5234541252" 

    mock(user).DoCheck # set expectation that DoCheck will be called 

    user.method1 # execute 
    end 
end 

更新

但要小心使用模仿對象和部分嘲笑的使用,因爲它們使您的測試代碼與測試中的代碼的當前行爲緊密耦合。如果將來要重構這些代碼,你可能會遇到很多失敗的測試(那些使用mock的測試)。嘗試測試代碼而不使用模擬(輸入輸出),並且只有在他們明確解釋受測試類的意圖時才使用模擬代碼。當你用mock編寫測試時總是問自己,你是否真的需要斷言這個方法調用另一個方法,或者你真正關心的是方法的輸出還是別的什麼。

希望這會有所幫助!

+0

非常感謝小費,我始終牢記在心,但不幸的是,我不能拿出另一個非模擬測試,這將足夠 –

+0

@MikeyS。,然後用嘲諷寫測試:)現在你需要的只是在測試中獲得更多練習。有了一些經驗,你會看到更好的方法來測試你現有的類。 另外還有一本關於如何爲現有代碼編寫測試的優秀書籍:[與Michael Feathers的遺留代碼有效地工作](http://www.amazon.com/Working-Effectively-Legacy-Michael-Feathers/dp/0131177052) 。 –

+0

再次感謝信息...我注意到的另一件事是,我不得不使用user.save!爲了讓if語句評估爲「true」(用戶明顯從ActiveRecord :: Base繼承),我不明白爲什麼,我創建的用戶實例位於內存中是不夠的? –