3

I have a SubscriptionHandler class with a call method that creates a pending subscription, attempts to bill the user and then error out if the billing fails. The pending subscription is created regardless of whether or not the billing fails

class SubscriptionHandler

  def initialize(customer, stripe_token)
    @customer = customer
    @stripe_token = stripe_token
  end

  def call
    create_pending_subscription
    attempt_charge!
    upgrade_subscription
  end

  private

  attr_reader :stripe_token, :customer

  def create_pending_subscription
   @subscription = Subscription.create(pending: true, customer_id: customer.id)
  end

  def attempt_charge!
    StripeCharger.new(stripe_token).charge!  #raises FailedPaymentError
  end

  def upgrade_subscription
   @subscription.update(pending: true)
  end

 end

Here is what my specs look like:

describe SubscriptionHandler do

  describe "#call" do
    it "creates a pending subscription" do
      customer = create(:customer)
      token = "token-xxx"
      charger = StripeCharger.new(token)
      allow(StripeCharger).to receive(:new).and_return(charger)
      allow(charger).to receive(:charge!).and_raise(FailedPaymentError)
      handler = SubscriptionHandler.new(customer, token)

      expect { handler.call }.to change { Subscription.count }.by(1) # Fails with FailedPaymentError
    end
  end
end

But this does not change the subscription count, it fails with the FailedPaymentError. Is there a way to check that the subscription count increases without the spec blowing up with FailedPaymentError.

2 Answers2

2

You should be able to use Rspec compound expectations for this

https://relishapp.com/rspec/rspec-expectations/docs/compound-expectations

So I'll re-write your expectation to something like this:

expect { handler.call }.
 to raise_error(FailedPaymentError).
 and change { Subscription.count }.by(1)
Adim
  • 1,716
  • 12
  • 13
0

It can be done like this

expect{ handler.call }.to raise_error FailedPaymentError

Should work.

If you don't want to raise error at all then you can remove this line, and return a valid response instead

allow(charger).to receive(:charge!).and_raise(FailedPaymentError)

More info - How to test exception raising in Rails/RSpec?

Official RSpec docs

https://relishapp.com/rspec/rspec-expectations/v/2-0/docs/matchers/expect-error

Rajdeep Singh
  • 17,621
  • 6
  • 53
  • 78