Question

First, I am a newb when it comes to writing tests in Rails. Thank you [upfront] for your patience.

Here is my class:

require 'json'

class Webhook
  attr_accessor :customer_id, :response, :event_type

  ACCEPTED_EVENTS = ["customer.subscription.deleted", "invoice.payment_succeeded", "invoice.payment_failed"]

  def initialize(json = nil)
    if json
      @response = JSON.parse(json, symbolize_names: true)
      @customer_id = @response[:data][:object][:customer]
      @event_type = @response[:type]
      @user = User.find_by_customer_id(@customer_id)
    end
  end

  def event_accepted?
    true if ACCEPTED_EVENTS.include?(@event_type)
  end

  def process
    return unless event_accepted?

    case @event_type
    when "invoice.payment_succeeded"
      begin
        invoice = Stripe::Invoice.retrieve(@response[:data][:object][:id])
        InvoiceMailer.payment_succeeded_email(@user, invoice).deliver if invoice.amount_due > 0
      rescue => e
        Rails.logger.info "An error as occurred! #{e}"
      end
    when "customer.subscription.deleted"
      @user.expire! if @user
    when "invoice.payment_failed"
      InvoiceMailer.payment_failed_email(@user).deliver
    end
  end
end

Here is my test thus far:

require 'spec_helper'

describe Webhook do

  describe "instance methods" do
    let(:webhook) { Webhook.new }

    describe "#event_accepted?" do
      it "returns true with a correct event_type" do
        webhook.event_type = "customer.subscription.deleted"
        webhook.event_accepted?.should be_true
      end

      it "returns false with an incorrect event_type" do
        webhook.event_type = "foobar123"
        webhook.event_accepted?.should be_false
      end
    end
  end
end

I am a little lost when it comes to trying to write tests for the #process method. Any help would greatly be appreciated!

Was it helpful?

Solution

You have 7 different paths to test for your process method. I am writing the test for two scenarios and leaving the rest for you to try. Also please note that my tests are under the assumption that the other methods process calls are tested separately.

There could be minor syntax/errors here because its untested. But it will give you an idea of how to test the process method

describe "Process" do
  it "should do nothing if the event is not accepted" do
    webhook = Webhook.new
    webhook.stub(:event_accepted?).and_return(false)
    InvoiceMailer.should_not_receive(:payment_succeeded_email)
    InvoiceMailer.should_not_receive(:payment_failed_email)
    webhook.process
  end

  it "should send a payment succeeded email if the event type is success" do
    customer = FactoryGirl.create(:user)
    webhook = Webhook.new({"type": "invoice.payment_succeeded", "data": {"object": {"id": 1, "customer": customer.id}}})
    Stripe::Invoic.should_receive(:retrieve).with("1").and_return(invoice = double("invoice", :amount_due => 20))
    InvoiceMailer.should_receive(:payment_succeeded_email).with(customer, invoice)
    webhook.process
  end

  it "should do nothing if the event type is success but the invoice due is zero" do
  end

  it "should log when there is an exception in processing the successful payment" do
  end

  it "should expire the user if the subscription is deleted" do
    customer = FactoryGirl.create(:user)
    webhook = Webhook.new({"type": "customer.subscription.deleted", "data": {"object": {"id": 1, "customer": customer.id}}})
    User.stub(:find_by_customer_id).with(customer.id).and_return(customer)
    customer.should_receive(:expire!)
    webhook.process
  end

  it "should do nothing if the subscription is deleted and the user is invalid" do
    webhook = Webhook.new({"type": "customer.subscription.deleted", "data": {"object": {"id": 1, "customer": customer.id}}})
    User.stub(:find_by_customer_id).with(customer.id).and_return(nil)
    User.any_instance.should_not_receive(:expire!)
    webhook.process
  end

  it "should send a failure email if the payment was not successful" do
  end
end
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top