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_receivecorrectly? 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_receiveexpectation 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_idonPlan, like this:(I am assuming that you meant to write
plan = Plan.find_by_id(params[:id])in the first line of yourdestroyaction.)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.