2011-03-09 66 views
12

我使用Rails 3.0.4和RSpec 2.5。在我的控制器,我使用大量命名範圍,例如Rails 3,RSpec 2.5:使用帶指定範圍的should_receive或stub_chain

 
    @collection = GuestbookEntry.nonreplies.bydate.inclusive.paginate(
     :page => params[:page], :conditions => { ... }) 

在我的測試中,我希望能夠嘲笑這樣的查詢,而不是措辭結果。我不認爲這樣做是有道理的做類似

 
    GuestbookEntry.stub_chain(:nonreplies, :bydate, ...).and_return(...) 

因爲這個測試將失敗,我決定重新排序命名範圍的時刻。

使用Rails 2.3和RSpec 1.x中,這個工作得很好:我可以寫

 
    GuestbookEntry.should_receive(:find).with(:all, :conditions => { ... }) 

和上面的通話將被捕獲並正確處理。但是,對於Rails 3,出於某種原因,這不再適用。

爲什麼?如何在嵌套範圍的結果上設置期望值或存根(stub)?由於Rails 3的ActiveModel中的所有內容都是命名範圍(感謝ARel),所以這一定是可能的,否則測試確實會非常脆弱。

謝謝!

更新:另請參閱issue report on GitHub

回答

1

這個問題已經困擾了我一段時間!

我相信行爲與Rails 2不同的原因是因爲查詢不再在控制器中的變量賦值期間執行。相反,它會根據需要進行延遲加載。

我同意Mark Wilden最好將所有這些範圍都包含在您的模型中的更大範圍和規範中。這個範圍顯然有一個特定的功能,所以就像人們會規定一個調用其他幾個方法的方法的行爲一樣,你可以規定一個範圍的行爲,它連接了其他幾個範圍。

0

我會在自己的範圍內包裝這樣一個複雜的查詢,並存根。

+0

那麼我該如何編寫驗證單個範圍做它應該做什麼的規範? 我的想法是編寫多個_simple_範圍,它們是_obvious_,因此幾乎沒有任何內部可以「出錯」,然後將它們合併,因爲它很難規範範圍(而不訴諸實際數據填充和查詢真實數據庫)。 – Jens 2011-04-27 05:25:13

+0

我認爲你必須規定每個「全範圍」,否則你不會知道你確實合併了它們。即使您指定正確的組合已經完成,您仍然需要一個總體規範來證明該組合本身是解決問題的正確方法。但是如果你把複雜的範圍放在自己的範圍內,你至少不必擔心「措辭」的順序,因爲它只能在一次地方完成。 我不認爲你可以擺脫填充數據庫。就我個人而言,我發現使用工廠建立真實數據比模擬模型方法更容易(和「更安全」)。 – 2011-04-27 16:21:37