deviseでcontrollerのテストを実施するための設定

deviseを導入後にcontrollerのテストを作成する場合、いくつかの設定を行う必要があります。その設定は以下の通りです。

設定について

deviseを導入した場合にはcontrollerのテストを実施するときに認証済みの状態とする必要があります。これは利用するモジュールによってもその状態が異なりますが、今回は confirmable モジュールを導入した状態を想定します。

前提条件

今回の設定では以下の条件であることを前提とします。

  • Rails 4.2.4 + devise 3.5.2を利用する
  • FactoryGirlであらかじめ必要なテストデータが作成できる状態である
  • ユーザーモデルには関連するモデルが存在する

1)rails_helperに設定を追加する

rails_helperにdeviseに関する設定を追加します。特に、参照については順序があるため順序を間違えないように設定します。

... 

# 'spec_helper'と'rspec/rails'のあとに  'devise'や 'support/controller_macros'を追加する。
require 'spec_helper'
require 'rspec/rails'
# Add additional requires below this line. Rails is not loaded until this point!

require 'devise'
require 'support/controller_macros'
...
RSpec.configure do |config|
...
# note:devise認証のための設定
  config.include Devise::TestHelpers, type: :controller
  config.extend ControllerMacros, type: :controller

  # FactoryGirlのシンタックスを省略する
  config.include FactoryGirl::Syntax::Methods
end
...

2)controller_macros.rbを作成する

認証をスキップするための具体的な処理を追加します。この処理では以下の点がポイントとなります。

  • 関連するモデルがある場合はあらかじめ作成する。
  • controllerのspecで作成したモデルを利用したい場合はインスタンス変数に保存しておく。
  • confirmableモジュールを利用しているため作成したユーザーは confirm! を実行しておく。
module ControllerMacros
  def login_user
    before(:each) do
      @request.env["devise.mapping"] = Devise.mappings[:user]
        
        # 本来は user のみを追加すれば良いが、関連するモデルが必要な場合は適宜追加する。
        # specで利用するためインスタンス変数に保存する。
      @login_org_user = create(:org_user, :admin)
      @user = @login_org_user.user

      # confirmable module を使用しているため confirm を実行する
      #@user.confirm!
      @user.confirm
      sign_in @user
    end
  end
end

3)controllerのspecを作成する

コントローラーでspecを作成します。このときには、controllers_macr.rb で作成した login_user をdescribeで定義することで実行することが可能となります。また、login_user内で設定したインスタンス変数についても同様に利用可能となります。

...
describe 'GET #index' do
    login_user

    it 'assigns all org_users as @org_users' do
      org_user = create(:org_user, :regular, :admin, organization: @login_org_user.organization)
      get :index, {}, valid_session
      expect(assigns(:org_users).to_a).to include(org_user)
    end
end
...

ほかにも機能があるようですが、基本的な利用については上記の処理で実施可能です。詳細な内容はHow To: Test controllers with Rails 3 and 4 (and RSpec) · plataformatec/devise Wiki · GitHub)を確認してください。