2016-02-19 65 views
-2

這裏是我的控制器規格Rspec的方法被稱爲2X,但無法找到第二次

before do 
    @order = Order.new 
end 
it "should call find & assign_attributes & test delivery_start methods" do 
    Order.should_receive(:find).with("1").and_return(@order) 
    Order.any_instance.should_receive(:assign_attributes).with({"id"=>"1", "cancel_reason" => "random"}).and_return(@order) 
    Order.any_instance.should_receive(:delivery_start).and_return(Time.now) 
    post :cancel, order: {id:1, cancel_reason:"random"} 
end 

失敗是這樣的:

Failure/Error: Unable to find matching line from backtrace 
    (#<Order:0x007fdcb03836e8>).delivery_start(any args) 
     expected: 1 time with any arguments 
     received: 2 times with any arguments 
# this backtrace line is ignored 

但我不知道爲什麼delivery_start是基於這個控制器動作被稱爲兩次:

def cancel 
    @order = Order.find(cancel_params[:id]) 
    @order.assign_attributes(cancel_params) 
    if (@order.delivery_start - Time.now) > 24.hours 
     if refund 
      @order.save 
      flash[:success] = "Your order has been successfully cancelled & refunded" 
      redirect_to root_path 
     else 
      flash[:danger] = "Sorry we could not process your cancellation, please try again" 
      render nothing: true 
     end 
    else 
     @order.save 
     flash[:success] = "Your order has been successfully cancelled" 
     redirect_to root_path 
    end 
end 
+0

對不起,但它「應該調用find&assign_attributes&test delivery_start方法」做 Order.should_receive(:find).with(「1」)。and_return(@order ) Order.any_instance.should_receive(:assign_attributes).with({「id」=>「1」,「cancel_reason」=>「random」})。and_return(@order)Order.any_instance.should_receive(:delivery_start) .and_return(Time.now) post:取消,order:{id:1,cancel_reason:「random」} end –

+0

我不確定,但我會猜測'delivery_start'可能合理地顯示在視圖正在顯示?這將是我猜測第二個「呼叫」來自何處。 –

+0

@TarynEast沒有相關的視圖,調用'delivery_start' – james

回答

0

我會建議更多的期望,並返回true或取決於您的使用。考慮以下更改

class SomeController < ApplicationController 
    def cancel 
    ... 
    if refundable? 
     ... 
    end 
    end 

    private 

    def refundable? 
    (@order.delivery_start - Time.now) > 24.hours 
    end 
end 

# spec/controllers/some_controller_spec.rb 
describe SomeController, type: :controller do 
    describe '#cancel' do 
    context 'when refundable' do 
     it 'cancels and refunds order' do 
     order = double(:order) 
     params = order: {id: '123', cancel_reason: "random"} 
     expect(Order).to receive(:find).with('123').and_return(order) 
     expect(order).to receive(:assign_attributes).with(params[:order]).and_return(order) 
     expect(controller).to receive(:refundable?).and_return(true) 
     expect(controller).to receive(:refund).and_return(true) 
     expect(order).to receive(:save).and_return(true) 
     post :cancel, params 
     expect(response).to redirect_to '/your_root_path' 
     expect(session[:flash]['flashes']).to eq({'success'=>'Your order has been successfully cancelled & refunded'}) 
     expect(assigns(:order)).to eq order 
     end 
    end 
    end 
end 
+0

感謝您的建議! – james

1

我建議您測試的行爲,而不是實施。雖然在某些情況下,您想要在控制器中標出數據庫,但是由於您正在測試控制器和模型層之間的集成,因此規範並不是一個好主意。

此外,您的測試只是測試您的控制器如何執行其工作 - 而不是其實際完成。

describe SomeController, type: :controller do 

    let(:order){ Order.create } # use let not ivars. 

    describe '#cancel' do 

    let(:valid_params) do 
     { order: {id: '123', cancel_reason: "random"} } 
    end 

    context 'when refundable' do 
     before { post :cancel, params } 
     it 'cancels the order' do 
     expect(order.reload.cancel_reason).to eq "random" 
     # although you should have a model method so you can do this: 
     # expect(order.cancelled?).to be_truthy 
     end 

     it 'redirects and notifies the user' do 
     expect(response).to redirect_to root_path 
     expect(flash[:success]).to eq 'Your order has been successfully cancelled & refunded' 
     end 
    end 
    end 
end 
+0

Max,這是一個公平的評論,但在這種情況下,測試是以這種方式設置的。還有其他的規格正在檢查控制器的方法是否按照他們應該的方式工作 – james

+0

是的?爲什麼問你是否不想修復它?但嘿它的你的應用程序。 – max

+0

呃...我的問題不是如何改變測試的本質,只是爲什麼一個特定的規格可能沒有通過 – james

0

對不起,這是一個非常不理想的答案,但我重新啓動我的電腦,並通過規範...

有一件事情一直討厭我之前,我已經忘記保存代碼,即測試運行的代碼的舊版本,稱爲delivery_start兩次。但在這種情況下,我確定檢查了我已經救了。我不知道爲什麼重新啓動修復它...