[英]Testing destroy method failure in Controller test
我有一個控制器,它破壞了我數據庫中的一個項目。 當前看起來像這樣:
before_filter(:except => :toggle_item_owned_state) do
@collection = current_user.collections.find(params[:collection_id])
end
def destroy
@item = @collection.items.find_by_id(params[:id])
if @item.destroy
redirect_to collection_items_path(@collection)
else
flash.now[:alert] = "There was a problem deleting this item."
redirect_to root_path
end
end
現在,我編寫了一些rspec控制器測試來驗證滿意的路徑,但是我想測試失敗的路徑(即@ item.destroy失敗時)。 我可以想象,執行此操作的正確方法是使用某種模擬或存根,但我無法提出可行的方法。
我嘗試了以下一些變化,但無法正常工作:
context "delete fails" do
before(:each) do
allow(@item).to receive(:destroy).and_return(false)
delete :destroy, :collection_id => batman_collection.id, :id => item_in_collection.id
end
it "will generate a flash error message" do
expect(flash[:alert]).to eq("There was a problem saving your collection.")
end
end
如果有人可以提供有關該操作方法的指導或示例代碼,我們將不勝感激。
謝謝
您如何在規范中設置@item
? 我懷疑它實際上並沒有被打斷。
更新:
在沒有看到您的控制器的情況下,我無法提供確切的代碼,但是通常情況是這樣的:
item = double
allow(Item).to receive(:find).and_return(item)
allow(item).to receive(:destroy).and_return(false)
更新2:
展開后,您可以通過以下方式設置item
:
current_user.collections.find(params[:collection_id]).items.find_by_id(params[:id])
這是一個很長的通話周期。 RSpec有解決此問題的方法,但是在“ 使用遺留代碼”一節中,它們說應將這些功能的使用視為一種代碼味道 。
改進代碼的一種方法是引入服務對象 :
class FindItem
def self.call(item_id, collection_id, user)
user.collections.find(params[:collection_id]).items.find_by_id(item)
end
end
這對於存根而言更加簡單,並且有助於將控制器與數據庫結構分離。 現在可以使用以下命令destroy
:
item = double
allow(FindItem).to receive(:call).and_return(item)
allow(item).to receive(:destroy).and_return(false)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.