This is my controller:
class PlansController
def use_new_card
@user = User.find_by_id(new_card_params[:user_id])
if new_stripe_card
...
end
private
def new_card_params
params.permit(:user_id, :stripeToken)
end
def new_stripe_card
StripeService.new({user_id: @user.id, customer_id: @user.stripe_customer_id, source: new_card_params[:stripeToken]}).new_card
end
end
I'm trying to write a controller spec that tests that when the proper parameters are POST
to the use_new_card
method, then new_stripe_card
's StripeService.new
gets these parameters appropriately.
My spec looks like this so far:
describe "when proper params are passed" do
before do
@user = User.create(...)
end
it "should allow StripeService.new to receive proper parameters" do
StripeService.should_receive(:new).with({user_id: @user.id, customer_id: @user.stripe_customer_id, source: "test"})
post :use_new_card, user_id: @user.id, stripeToken: "test"
end
end
But with that I'm getting
Failure/Error: post :use_new_card, user_id: @user.id, stripeToken: "test"
NoMethodError:
undefined method `new_card' for nil:NilClass
Totally fair, but I'm not sure how to fix this... I can't just stub new_card
because a stubbed method on a nil
object will still throw this error (I tried adding a StripeService.any_instance.stub(:new_card).and_return(true)
already into the before
block)
Stubbed methods return
nil
by default. Useand_return
to specify the value returned by the stub::or using the newer syntax
EDIT
Pardon my hand-waving. Your stub must return an object that will act like an instance of
StripeService
to the extent required for the purposes of the test. So for example:Now when the test refers to
new_stripe_service
, RSpec will return a test double that has a method stub named#new_card
, which itself is a double. You can add whatever additional stubs you need to make the test pass. Alternatively, you can return an actual instance ofStripeService
fornew_stripe_service
.