这是我的控制器规范
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 :(得分: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
答案 1 :(得分:0)
我建议更多的期望,并根据您的使用返回真或假。请考虑以下更改
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
答案 2 :(得分:0)
对不起,这是一个非常不令人满意的答案,但我重新启动了我的电脑并且规范通过了......
之前令我讨厌的一件事是,我忘记了保存代码,即测试运行的代码的旧版本被称为delivery_start
两次。但在这种情况下,我肯定检查过我已经救了。我不知道为什么重启会修复它...