A developer notebook I should have started 10 years ago..

RSpec expectations chaining

How can I chain RSpec expectations?

# chaining multiple changes assertions
expect { user.destroy }
  .to change { User.count }.by(-1)
  .and change { Group.count }.by(-1)

# chaining optional assertions
expect(color)
  .to eq("blue")
  .or eq("red")

Testing a base controller with RSpec

TLDR

How can I test a base controller (without actions) in RSpec?

RSpec.describe BaseController, type: :controller do
  controller do
    def index; end
  end

  # my tests
  ...
end

It’s very usual to have multiple base controllers classes in a Rails application. One for the API, one for the admin part…

Most of the time, these controllers have no actions. So how can we test them?

Here is our Webhooks base controller that many other controllers will inherit.

class WebhooksController < ApplicationController
  before_action :verify_signature

  private 
  
  def verify_signature
    ...
  end
end

This controller includes only one before_action callback but no actions.

Adding the controller block at the top of the controller, can define actions and request the base controller for testing.

RSpec.describe WebhooksController, type: :controller do
  controller do
    def index; end
  end

  describe "Signature checks" do
    context "when the signature is not found" do
      it "returns an unauthorized response" do
        get :index
        expect(response).to have_http_status(:unauthorized)
      end
    end
  end
end

Resources: