我有一个看起来像这样的约会控制器:
class AppointmentsController < ApplicationController
def update
@appointment = Appointment.find(params[:id])
if @appointment.update_attributes(params[:appointment])
@appointment.update_order_time_remaining
redirect_to order_path(@appointment.order)
else
redirect_to :back
end
end
end
我正在尝试编写一个测试,以验证在@appointment上调用update_order_time_remaining
。测试看起来像:
RSpec.describe AppointmentsController, :type => :controller do
describe "PUT update" do
it "calls update_order_time_remaining" do
@appt = Appointment.create(FactoryGirl.attributes_for(:appointment))
expect(controller.instance_variable_get :@appointment).to receive(:update_order_time_remaining)
put :update, appointment: {status: 'confirmed'}, id: @appt.id
end
end
end
代码已经简化了一点。我有其他约会控制器测试正在通过,但我不能让这个测试通过。我一直收到失败的消息:
Failure/Error: expect(controller.instance_variable_get :@appointment).to receive(:update_order_time_remaining)
(#<Appointment:0x00000009044b48>).update_order_time_remaining(*(any args))
expected: 1 time with any arguments
received: 0 times with any arguments
我还尝试使用assigns(:appointment)
代替controller.instance_variable_get :@appointment
我使用此代码进行测试:
it "calls update_order_time_remaining" do
@appt = Appointment.create(FactoryGirl.attributes_for(:appointment))
expect_any_instance_of(Appointment).to receive(:update_order_time_remaining)
put :update, appointment: {durations: ['60'], status: 'confirmed'}, id: @appt.rand_id
end
这似乎有些不准确,但你觉得这已经足够了吗?
答案 0 :(得分:0)
也可能没事。
另一个选择是让约会返回完全相同的实例,例如:
expect(Appointment).to receive(:find).with(appt.rand_id).and_return(appt)
expect(appt).to receive(:update_order_time_remaining)
(在这种情况下不需要在测试中使用实例变量)
在这种情况下,您可以使用mock
(而不是实际创建的记录)来更快地进行测试。
为什么要用如此奇怪的代码创建约会?
Appointment.create(FactoryGirl.attributes_for(:appointment))
如果内置记录无效,则不会保存到DB,但您不会知道。这可能导致奇怪的测试失败。
1)FactoryGirl具有创建方法,该方法较短,如果出现错误则会失败
2)如果您的记录无效,最好使用爆炸版本create!
失败
UPD 示例测试:
it "calls update_order_time_remaining" do
appointment = FactoryGirl.build_stubbed(:appointment)
expect(Appointment).to receive(:find).with(appointment.rand_id).and_return(appointment)
expect(appointment).to receive(:update_order_time_remaining)
put :update, appointment: {durations: ['60'], status: 'confirmed'}, id: appointment.rand_id
end