Ruby on rails 使用Rspec-should\u-receive测试控制器是否正确调用对象上的方法
好的,首先,我应该说,虽然我已经读了很多关于Ruby on rails 使用Rspec-should\u-receive测试控制器是否正确调用对象上的方法,ruby-on-rails,ruby,ruby-on-rails-4,rspec,rspec-rails,Ruby On Rails,Ruby,Ruby On Rails 4,Rspec,Rspec Rails,好的,首先,我应该说,虽然我已经读了很多关于应该接收,但我仍然不能完全确定我是否理解它背后的概念,因此我所做的可能是完全不可能的 我有以下资料: class PlansController def destroy plan = plan.find_by_id(params[:id]) if plan.cancel_stripe_subscription(params[:reason]) flash[:success] = "success" redir
应该接收
,但我仍然不能完全确定我是否理解它背后的概念,因此我所做的可能是完全不可能的
我有以下资料:
class PlansController
def destroy
plan = plan.find_by_id(params[:id])
if plan.cancel_stripe_subscription(params[:reason])
flash[:success] = "success"
redirect_to root_path
else
#error handling
end
end
end
class Plan
def cancel_stripe_subscription(reason)
self.status = "canceled"
self.cancellation_reason = reason
if self.save
return true
else
return false
end
end
在我的控制器规范中,我认为有必要进行一项测试,即使用正确的参数和所有内容成功调用cancel\u stripe\u subscription
方法(使用1 should\u receive1),并进行另一项测试,以确保destroy
操作的输出正确
换句话说,我想编写以下控制器规范:
describe PlansController, "Destroy Action" do
before do
@plan = Plan.create(...)
end
it "should have called destroy action" do
delete :destroy,
plan: {
id: @plan.id,
reason: "something"
}
assigns(:plan).should_receive(:cancel_stripe_subscription).with(reason:"something").exactly(1).times.and_return(true)
end
it "should have called destroy action" do
delete :destroy,
plan: {
id: @plan.id,
reason: "something"
}
assigns(:plan).status.should == "canceled"
assigns(:plan).cancellation_reason.should == "something"
end
end
第二个测试通过,但第一个测试抛出
Failure/Error: assigns(:plan).should_receive(:cancel_stripe_subscription)
(#<Plan:0x007fe282931310>).cancel_stripe_subscription(*(any args))
expected: 1 time with any arguments
received: 0 times with any arguments
失败/错误:分配(:计划)。是否应接收(:取消订阅)
(#)取消订阅(*(任何参数))
预期:1次,有任何参数
收到:0次,有任何参数
所以我有两个问题:
是否应该接收?我应该测试一下吗?或者第二次测试被普遍认为足够了
expect(@plan)的运气不好。收到(:取消订阅)
在调用测试中的方法之前,必须设置
应该接收的期望值;你以后再定。由于您需要在之前进行设置,因此您必须确保设置了期望的对象最终在操作中被操作。通常的方法是在计划
上删除按id查找,如下所示:
it "should have called destroy action" do
Plan.stub(:find_by_id).and_return(@plan)
assigns(:plan).should_receive(:cancel_stripe_subscription).with(reason:"something").exactly(1).times.and_return(true)
delete :destroy, plan: { id: @plan.id, reason: "something" }
end
(我假设您打算编写plan=plan.find by_id(params[:id])
在destroy
操作的第一行。)
至于你是否应该以这种方式进行测试,我想说你的第二次测试在验证你想要的结果方面做得足够好,而且你真的不需要费事。我认为这里的混乱部分是由于结合了两种不同的测试风格,mockist(你的第一次测试)和Classisist(你的第二次测试). 根据您喜欢的测试风格,可以使用其中一种,但同时使用这两种方法来测试同一段代码有点多余。好的,我想我在这里有点过于密集,我不完全确定我是否理解其中的差异。my way和your way都会先调用delete:destroy
,然后检查分配(:plan)。应该接收,这样就不会有什么不同了。但是当我使用创建的@plan
时,您正在存根一个计划。这是否意味着必须将plan对象存根为should\u receive
才能工作,因为否则您可能已经在真实的@plan
对象上调用了该方法,因此它不再是可测试的?我说得通吗?你很困惑,因为我犯了一个错误,把陈述的顺序弄错了。现在修好了。:)哦,这对我来说太奇怪和不舒服了。。。我将继续我的第二次测试(谢谢!