title: How do I test stripe and my controller effectively?
body: <p>I have the following models:
  <code>subscription</code>, <code>user</code>, and <code>events</code></p>
  
  <ul>
  <li>A <code>user</code> <code>has_one</code> <code>subscription</code></li>
  <li>A <code>subscription</code> <code>belongs_to</code> a <code>user</code></li>
  <li>A <code>user</code> <code>has_many</code> <code>events</code></li>
  <li>An <code>event</code> <code>belongs_to</code> a <code>user</code></li>
  </ul>
  
  <p>So far I have been able to successfully create acceptance tests using Capybara and RSpec. This allows me to 'upgrade' a users account (which adds a different role). I've also been able to do an acceptance test where the user cancels their subscription and ensure their roles are removed. </p>
  
  <p>However, now I want to ensure that any of the user's open events are cancelled. This is where I'm getting stuck. Actually, I didn't even get this far because I ran in to trouble trying to even destroy a subscription.</p>
  
  <p>So, I created a controller spec called <code>subscriptions_controller_spec.rb</code>. In this spec, there is a test to ensure the <code>destroy</code> action works as expected. This is failing because in my controller it goes to retrieve the customer and subscription, which doesn't exist, and returns an <code>Stripe::InvalidRequestError</code>.</p>
  
  <p>In order to get around this, I tried to use <code>stripe-ruby-mock</code> to mock the stripe servers. However, I'm not sure how I'm supposed to use this in a controller spec and I got really confused. Below is my controller and my controller spec. Any advice on how I should attack this would be really appreciated.</p>
  
  <p><code>subscriptions_controller_spec.rb</code></p>
  
  <pre><code>require 'rails_helper'
  
  RSpec.describe SubscriptionsController, :type =&gt; :controller do
  
    let(:stripe_helper) { StripeMock.create_test_helper }
    before { StripeMock.start }
    after { StripeMock.stop }
  
    # ... omitted 
  
    describe 'DELETE destroy' do
      before :each do
        sign_in_trainer
        @subscription = create(:subscription, user: subject.current_user)
        plan = stripe_helper.create_plan(:id =&gt; 'Standard')
        customer = Stripe::Customer.create({
                                              email: 'johnny@appleseed.com',
                                              source: stripe_helper.generate_card_token,
                                              plan: 'Standard'
                                          })
        @subscription.customer_id = customer.id
        @subscription.stripe_sub_id = customer.subscriptions.data.first.id
      end
  
      it 'destroys the requested subscription' do
        expect {
          delete :destroy, {:id =&gt; @subscription.to_param}
        }.to change(Subscription, :count).by(-1)
      end
  
      # ... omitted
  
    end
  end
  </code></pre>
  
  <p>And <code>subscriptions_controller.rb</code></p>
  
  <pre><code>class SubscriptionsController &lt; ApplicationController
    before_action :set_subscription, only: [:update, :destroy]
  
    # ... ommitted
  
    # DELETE /cancel-subscriptions/1
    def destroy
      begin
        customer = Stripe::Customer.retrieve(@subscription.customer_id)
        customer.subscriptions.retrieve(@subscription.stripe_sub_id).delete
      rescue Stripe::CardError =&gt; e
        # User's card was declined for many magnitude of reasons
        redirect_to user_dashboard_path, alert: 'There was a problem cancelling your subscription' and return
      rescue Stripe::APIConnectionError =&gt; e
        # Stripe network issues
        redirect_to user_dashboard_path, alert: 'Network issue. Please try again later' and return
      rescue Stripe::APIError =&gt; e
        # Stripe network issues
        redirect_to user_dashboard_path, alert: 'Network issue. Please try again later' and return
      rescue Stripe::InvalidRequestError =&gt; e
        # This is something that we screwed up in our programming. This should literally never happen.
        redirect_to user_dashboard_path, alert: 'There was a problem cancelling your subscription.' and return
      rescue =&gt; e
        logger.error e.message
        logger.error e.backtrace.join("\n")
        redirect_to user_dashboard_path, alert: 'There was a problem cancelling your subscription.' and return
      end
  
      if current_user.events
        @events = current_user.events
        @events.open.each do |event|
          event.cancel
        end
      end
  
      current_user.remove_role 'trainer'
      current_user.add_role 'user'
      current_user.save
      @subscription.destroy
      respond_to do |format|
        format.html { redirect_to user_dashboard_path, notice: 'Subscription cancelled. All your open events have been cancelled.' }
        format.json { head :no_content }
      end
    end
  
    private
    # Use callbacks to share common setup or constraints between actions.
    def set_subscription
      @subscription = Subscription.find(params[:id])
    end
  
    # Never trust parameters from the scary internet, only allow the white list through.
    def subscription_params
      params[:subscription]
    end
  end
  </code></pre>