Edited at

rspecのテスト環境でdeviseにログインする方法【rails】

More than 1 year has passed since last update.


やりたいこと

rspecを使ったテストの中でcurrent_userとかを使いたい


方針

テストの中で、deviseのログイン状態を擬似的に作る。

具体的にはuserのデータを生成し、ログインをbefore doの中で行う。


導入したgem

gem 'devise'

gem 'rspec-rails'
gem 'factory_girl_rails'
gem 'faker'
gem 'rails-controller-testing'

railsのバージョンによってはrails-controller-testingは、Gemfileに記述を書いてbundle installしても入らないことがあるっぽいです。

その時は下記をどうぞ。

$ gem install rails-controller-testing

下記を試せば、gemの名前にconが含まれるものだけ検索できて、導入できたか確かめられます。

$ gem list con

=> rails-controller-testing (1.0.1)

公式ドキュメント:rails/rails-controller-testing



どうやるか


  • support/controller_macrosを作成、ログインのためのコードを記述

  • rails_heplerにdeviseとmacrosの読み込みを記述

  • spec/factories/user.rbの作成

  • controllerにbefore doを記述しログインさせる


実装


1. controller_macrosの作成

spec/support/controller_macros.rbを作成し、下記の内容を追記してください。


spec/support/controller_macros.rb

module ControllerMacros

def login_admin(admin)
@request.env["devise.mapping"] = Devise.mappings[:admin]
sign_in admin
end

def login_user(user)
controller.stub(:authenticate_user!).and_return true
@request.env["devise.mapping"] = Devise.mappings[:user]
sign_in user
end
end



2. rails_helper内でdeviseとcontroler_macrosを読み込む

rails_helperのRSpec.configure外に以下を記述し、deviseとmacrosを読み込みます。


spec/rails_helper.rb

require 'devise'

require File.expand_path("spec/support/controller_macros.rb")

RSpec.configure内に以下を記述し、deviseのtest_helperとmacrosをcontroller内で使えるようにします。


spec/rails_helper.rb

RSpec.configure do |config|

config.include Devise::TestHelpers, type: :controller
config.include ControllerMacros, type: :controller
end



3. FactoryGirlとFakerを使い、userモデルを作成

以下を記述することで、FactoryGirlを使う時に記述を減らすことができます。


rails_helper.rb

RSpec.configure do |config|

config.include FactoryGirl::Syntax::Methods
end

# 記述なし

FactoryGirl.create(:user)

#記述あり
create(:user)


FactoryGirlで使うuserのモデルを作成します。

Fakerを使い、全てのデータを生成しています。

passwordとpassword_confirmationを同じデータにするために、passを定義してそれを代入する形となっています。


spec/factories/user.rb

FactoryGirl.define do

pass = Faker::Internet.password(8)

factory :user do
name Faker::Name.name
email Faker::Internet.email
password pass
password_confirmation pass
end
end



4. controller_spec.rbで、userをcreateしログイン処理をする

createしたuserをletに格納しインスタンス変数のように使用できるようにしました。

さらにそのuserにlogin_userメソッドを使ってdeviseにログインさせます。


message_controller_spec.rb

require 'rails_helper'

describe MessagesController, type: :controller do
let(:user) { create(:user) }
# userをcreateし、let内に格納

describe 'GET #index' do
before do
login_user user
# controller_macros.rb内のlogin_userメソッドを呼び出し
end

it "renders the :index template" do
end
end



何ができるようになったか

current_userなど、deviseのヘルパーメソッドを使用したインスタンス変数のテストが出来るようになりました。


message_controller.rb

  def index

@groups = current_user.groups
end

上記のコードはアソシエーションを組まないと動かないのですが、

RSpecテスト内でのアソシエーションの組み方はこちらをどうぞ。


番外編;最近買った、面白いもの

・ハンターハンター34巻(6/29)

クロロ VS ヒソカとか、どうやっても面白くなるとしか

・カーテン自動開閉ロボット

カーテンレールに付ける4000円のロボット。

これを付けてから目覚ましなしで起きられる率が上がった。

・衛藤美彩 写真集

「綺麗なお姉さん」が好きな人、ちょっと眺めてるだけで幸せになれますよ。


参考サイト様

deviseで認証しているログイン必須のRspec controllerテスト

deviseを使ったコントローラのテスト