OK first, I should say while I've read a lot about should_receive
, I'm still not entirely sure I'm understanding the concept behind it, so what I'm doing could potentially be completely not possible.
I have the following:
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
In my controller spec, I am thinking it makes sense to do a test that the cancel_stripe_subscription
method is called successfully (using 1should_receive1), with the right arguments and everything, and another test that the output of the destroy
action is correct.
In other words, I thought to write the following controller spec:
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
The second test passes, but the first throws
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
So I really have two questions:
- Just to confirm, am I using
should_receive
correctly? Should I even be testing for this? Or is the second test generally accepted as enough? - If I should be testing for this, what's the right way of using
should_receive
? (Note, have not had luck withexpect(@plan).to have_received(:cancel_stripe_subscription)
either)
A
should_receive
expectation has to be set before you call the method under test; you're setting it afterwards. Since you need to set it before, you then have to make sure the object you've set up the expectation on ends up being operated on in the action. The normal way would be to stub outfind_by_id
onPlan
, like this:(I am assuming that you meant to write
plan = Plan.find_by_id(params[:id])
in the first line of yourdestroy
action.)As to whether you should be testing it this way, I'd say that your second test does a good enough job of verifying the outcome that you want, and you don't really need to go to all the trouble.