brandon.hornseth

Testing Controller Concerns with Minitest

tech

While RSpec is extremely popular in the Ruby community, I prefer to have less magic and better readability in my test suites. That means I use Minitest whenever I can.

There seems to be endless documentation for how to test Rails controller concerns with RSpec and little to none for Minitest so I decided to put together a quick writeup on how I’ve been going about it.

Let’s start with an example controller concern that sets a @current_user instance variable:

# app/controllers/concerns/user_context_concern.rb
module UserContext
  extend ActiveSupport::Concern

  included do
    before_action :set_current_user
  end

  def set_current_user
    @current_user = if session[:user_id]
                      User.find(session[:user_id])
                    else
                      NullUser.new
                    end
  end
end

Now let’s take a look at a simple test case for this module:

# test/controllers/concerns/user_context_concern_test.rb
require 'test_helper'

class UserContextConcernTest < ActionController::TestCase
  controller(ApplicationController) do
    include UserContextConcern

    # Create a simple action that renders text
    def index
      render plain: "Hello world"
    end
  end

  test "@current_user is a NullUser when session is empty" do
    get :index

    # this assertion would fail if an unhandled error occurred
    assert_reponse :success

    # Assert our controller concern code ran
    assert_instance_of NullUser, assigns(:current_user)
  end
end

This test creates an ephemeral controller class that includes our controller concern and an index method that simply renders a plain text response. The test case calls that index method, asserts we got a 200 OK reponse and the @current_user assignment is an instance of the NullUser class. That’s all there is to it!