簡體   English   中英

在Controller測試中測試銷毀方法失敗

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM