2014-01-08 59 views
0

我正在測試緩存過期,並且在創建新的ProjectInfo時,項目以及ProjectInfos的緩存應該過期。我有以下測試:無法找出此rspec錯誤

it "creating a new project info should invalidate the cache" do 
     2.times { FactoryGirl.create(:project_info) } 
     ProjectInfo.should_receive(:all).and_call_original 
     Project.should_receive(:all).and_call_original 
     Project.fetch_all 

     Project.should_not_receive(:all) 
     Project.fetch_all 
     ProjectInfo.should_not_receive(:all) 
     ProjectInfo.fetch_all 

     FactoryGirl.create(:project_info) 
     Project.should_receive(:all).and_call_original 
     Project.fetch_all <- problem line 
     ProjectInfo.should_receive(:all).and_call_original 
     ProjectInfo.fetch_all 
    end 

我得到以下錯誤:

1) ProjectInfo Caching creating a new project should invalidate the cache 
    Failure/Error: Project.fetch_all 

Project(id:integer, name:string).all({:include => :project_info}) 
expected: 0 times with any arguments 
    received: 1 time with arguments: ({:include=>:project_info}) 

問題的行,如果最後Project.fetch_all。爲什麼rspec期待它0次?

回答

0

我認爲它有一定的事Project.should_not_receive(:all)fetch_all可能會調用all

你可以嘗試沒有Project.should_not_receive(:all)

1

摘要

同樣的例子在同一對象上設置一個消極的期望後,您不能設置一個積極的期望的對象上。

詳細

我不知道設置的東西,已經有一組期望時預期RSpec的行爲被正式定義。我製作了一套測試,其結果如下所示,試圖提出一個統一的模型。

從概念上講,至少,RSpec將每個對象#方法的期望值置於對象#方法特定的FIFO隊列中,然後在每個方法調用和塊末尾檢查針對該隊列的期望值。如果對隊列中的條目的期望是「滿足的」,則期望遞減或去除(如果遞減爲0)。如果期望未得到滿足,那麼期望就會失敗。

鑑於此場景,如果調用該方法,在「should_not_receive」之後放置「should_receive」將始終失敗,如同您的情況。

此問題的解決方案和RSpec打算的方法是將您的單個示例分解爲多個示例,以便您不會在同一示例中對相同對象#方法對設置兩次期望。

請注意,在下面的示例中,我在RSpec報告錯誤的行上顯示錯誤。如果調用不是預期的,那將是調用的行。在調用期望被設置但在塊結束時不滿意的情況下,這將是設定期望的行。

class Foo; end 

describe "multiple expectations on same object with single it clause" do 
    it "yes, doit" do # succeeds 
    Foo.should_receive(:bar) 
    Foo.bar 
    end 
    it "no, yes, doit" do 
    Foo.should_not_receive(:bar) 
    Foo.should_receive(:bar) 
    Foo.bar # fails, expected 0, received 1 
    end 
    it "yes, doit, no" do # succeeds 
    Foo.should_receive(:bar) 
    Foo.bar 
    Foo.should_not_receive(:bar) 
    end 
    it "yes, doit, yes, doit" do # succeeds 
    Foo.should_receive(:bar) 
    Foo.bar 
    Foo.should_receive(:bar) 
    Foo.bar 
    end 
    it "yes, yes, doit, doit" do # succeeds 
    Foo.should_receive(:bar) 
    Foo.should_receive(:bar) 
    Foo.bar 
    Foo.bar 
    end 
    it "yes, yes, doit" do 
    Foo.should_receive(:bar) 
    Foo.should_receive(:bar) # fails, expected 1, received 0 
    Foo.bar 
    end 
    it "yes, yes" do 
    Foo.should_receive(:bar) # fails, expected 1, received 0 
    Foo.should_receive(:bar) 
    end 
    it "yes, no" do 
    Foo.should_receive(:bar) # fails, expected 1, received 0 
    Foo.should_not_receive(:bar) 
    end 
    it "no, yes" do 
    Foo.should_not_receive(:bar) 
    Foo.should_receive(:bar) # fails, expected 1, received 0 
    end 
    it "yes(2), doit, yes, doit, doit" do # succeeds 
    Foo.should_receive(:bar).exactly(2).times 
    Foo.bar 
    Foo.should_receive(:bar) 
    Foo.bar 
    Foo.bar 
    end 
end