やりたいこと
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を作成し、下記の内容を追記してください。
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を読み込みます。
require 'devise'
require File.expand_path("spec/support/controller_macros.rb")
RSpec.configure内に以下を記述し、deviseのtest_helperとmacrosをcontroller内で使えるようにします。
RSpec.configure do |config|
config.include Devise::TestHelpers, type: :controller
config.include ControllerMacros, type: :controller
end
3. FactoryGirlとFakerを使い、userモデルを作成
以下を記述することで、FactoryGirlを使う時に記述を減らすことができます。
RSpec.configure do |config|
config.include FactoryGirl::Syntax::Methods
end
# 記述なし
FactoryGirl.create(:user)
#記述あり
create(:user)
FactoryGirlで使うuserのモデルを作成します。
Fakerを使い、全てのデータを生成しています。
passwordとpassword_confirmationを同じデータにするために、passを定義してそれを代入する形となっています。
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にログインさせます。
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のヘルパーメソッドを使用したインスタンス変数のテストが出来るようになりました。
def index
@groups = current_user.groups
end
上記のコードはアソシエーションを組まないと動かないのですが、
RSpecテスト内でのアソシエーションの組み方はこちらをどうぞ。
##番外編;最近買った、面白いもの
・ハンターハンター34巻(6/29)
クロロ VS ヒソカとか、どうやっても面白くなるとしか
・カーテン自動開閉ロボット
カーテンレールに付ける4000円のロボット。
これを付けてから目覚ましなしで起きられる率が上がった。
・衛藤美彩 写真集
「綺麗なお姉さん」が好きな人、ちょっと眺めてるだけで幸せになれますよ。