2011-05-11 96 views
8

塊在我的什麼我實際上做的,比方說我有2個調用數據庫簡化的例子:測試方法包裹在使用RSpec

Repo.add(something_stringy) 
Repo.remove(something_floaty) 

,我想用嘲弄的數據庫調用,作爲真正的通話將被其他地方進行測試:

let(:repo){ 
    repo = double("Repo") 
    repo.should_receive(:add).with(instance_of(String)) 
    repo.should_receive(:remove).with(instance_of(Float)) 
    repo 
} 

before { FakeKlass.const_set :Repo, repo } 

這是所有罰款和花花公子,但現在如果我換在一個事務中我有點難倒了電話:

Repo.transaction do 
    # ... some error checking in here somewhere... 
    Repo.add(something_stringy) 
    Repo.remove(something_floaty) 
end 

因爲如果我寫的接收transaction它會接聽電話,但一切都在塊將不會被調用,我也得到一個模擬:

預期:1時收到 :0次

所有其他模擬。任何人都可以告訴我應該如何寫我的規格來處理這個問題?我試過閱讀RSpec書中關於around(:each)的相關頁面,但這對我來說就像泥土一樣清晰。

任何幫助,非常感謝。

回答

12

您可以使用#and_yield從一個期望鏈產生:

repo.should_receive(:transaction).and_yield 

你也不需要設置一個雙存根出你的回購類的方法。例如,你的設置可以寫成:

before(:each) do 
    Repo.should_receive(:transaction).and_yield 
    Repo.should_receive(:add).with(instance_of(String)) 
    Repo.should_receive(:remove).with(instance_of(Float)) 
end 

您也可以考慮使用stub代替should_receive,因爲它不成立的期望:

before(:each) do 
    Repo.stub(:transaction).and_yield 
    Repo.stub(:add) 
    Repo.stub(:remove) 
end 

一般情況下,你應該只使用should_receive當你想測試兩個對象之間的交互時。我個人的經驗法則是,如果出現在before中,請使用stub;如果它是一個示例,尤其是具有特定值,請使用should_receive

+0

謝謝,真的很有幫助。 – iain 2011-05-12 22:25:41

+0

謝謝,這也幫助我測試Redis.pipelined包裝代碼,它的行爲與交易類似。 – 2012-11-21 01:17:49