2013-04-29 51 views
0

我試圖創建使用模型的一個RSpec模擬控制器上的測試,它似乎只有在工作的時候說RSpec的嘲諷不會被調用

Type.any_instance.should_recieve(...) 

,而不是

instancename.should_receive(...) 

我的代碼看起來像這樣。 (一般我用FactoryGirl,但我不是在這個例子中,以確保它不是問題)

it "calls blah on foo" do 
    foo = Foo.new 
    foo.save 
    foo.should_receive(:blah) #this fails because it's called 0 times 
    #Foo.any_instance.should_receive(:blah) #this would succeed 
    post :create, {:foo => foo} 
end 

,並在我的控制器

def create 
    foo = Foo.find_by_id(params[:foo]) 
    foo.blah 
    #other stuff thats not related 
end 

我知道我可以嘲笑Foo.find_by_id和有它返回foo,但我覺得我不應該這樣做,因爲它應該被返回,這意味着如果我停止使用find_by_id,測試會中斷,這實際上不是一個重要的細節。

任何想法我做錯了什麼?如果我不必在任何地方說any_instance,並且不必模擬find_by_id,我覺得我的測試會更好。

回答

2

您的代碼不起作用,因爲它不相同foo對象在您的實際代碼中正在調用blah

在你規範的代碼,您創建一個實例,並將其保存:

foo = Foo.new 
foo.save 

這樣可以節省記錄到數據庫,這foo點。然後你把一個期望的對象:

foo.should_receive(:blah) 

這種期望只會工作,如果規範和應用程序代碼都指向同一個對象。正如你注意到的那樣,你可以通過例如存檔find_by_id來返回它。或者,您也可以對任何實例設置期望值,您也會注意到這一點。

但是,期望不會按原樣工作。在您的實際代碼,您可以創建一個不同對象foo

foo = Foo.find_by_id(params[:foo]) 
foo.blah 

如果params[:foo]是記錄的ID,然後在規範的代碼都foofoo在您的應用程序代碼都指向同一個記錄,但這並不意味着它們是同一個對象(它們不是)。

另外,如果我理解正確的話,我相信這一點:

post :create, {:foo => foo} 

應該是:

post :create, {:foo => foo.id} 

因此,概括地說,如果你想要的是一個消息的期望,你」你需要或者存根find或應用期望在任何情況下。 (請注意,您應該能夠存根find而不是find_by_id,因爲無論如何動態查找器都會調用find,這應該使您的測試更加健壯。)

希望有幫助。

+0

謝謝。這就是我在想什麼,我只是希望有一種方式不需要調用find_by_id。調用查找似乎是一個更好的解決方案,所以我會這樣做。 – bdwain 2013-04-29 05:34:20

+0

只是一個領導。我不認爲有關find_by_id調用的部分找到了作品。我試過了,直到我找到find_by_id爲止。 – bdwain 2013-04-29 06:09:27

+0

對不起,我必須回顧一下,我以爲我在某個地方做過,但我可能是錯的。我會盡快給您回覆。 – 2013-04-29 11:14:40