rails tutorialを参考にログイン機能やbefore_actionにてログイン済みのみができるアクションを実装しました。
そのテストコードにおいてログインの有無の2パターンでテストを実行したいと思います。
ログインをしていない場合は、単純に制限のあるURLをgetすれば再現できると考えています。
ログインしている場合は、postリクエスト及び必要情報を渡すことでログインを再現できるのではないかと思います。
このことから、下記の通りにテストコードを記述して見ました。が、rspecのログを確認するとログインできていない動作になっております。
helperにてログイン状態を再現するメソッドを定義
testhelper
1include ApplicationHelper 2 3module TestHelper 4 def log_in_as(user, remember_me: '1') 5 post login_path, params: { session: { 6 email: user.email, 7 password: user.password, 8 remember_me: remember_me 9 } } 10 end 11end
テストヘルパーを全てのスペックで使用できるようにinclude済み
railshelper
1RSpec.configure do |config| 2 config.include TestHelper 3end
factorybot
1FactoryBot.define do 2 factory :user, class: :user do 3 name { Faker::Name.name } 4 sequence(:email) { |n| "example#{n}@example.com" } 5 image { Rack::Test::UploadedFile.new(File.join(Rails.root, 'spec/fixtures/test.jpg')) } 6 7 password { 'foobar' } 8 password_confirmation { 'foobar' } 9 10 trait :admin do 11 admin { true } 12 end 13 end 14end
UsersRequestSpec
1describe 'GET #index' do 2 subject { response } 3 # ユーザーのログインの有無を確認 4 describe 'before_action :logged_in_user' do 5 let!(:user) { FactoryBot.create(:user) } 6 # ユーザーがログインしている場合 7 context 'The user is logged in' do 8 before do 9 log_in_as(user) ← ログイン状態を再現しているはず 10 get users_path 11 end 12 it 'responds successfully' do 13 is_expected.to be_successful 14 end 15 16 it 'returns a 200 response' do 17 is_expected.to have_http_status(200) 18 end 19 end 20 end
赤線部分が疑問な箇所になりまして、一本目ではpostした情報を元にuserをログインし、2本目でusers/1(user.id)にアクセスしているのでここまでは期待した動作になっています。しかし、その後にredirectで/loginにアクセスしています。
usercontrollerを下記の通りに示します。(抜粋)
UserController
1before_action :logged_in_user, only: %i[index edit update destroy] 2 3 PER = 10 4 5 def index 6 @users = User.page(params[:page]).per(PER) 7 end 8 9private 10 # ログイン済みユーザーかどうか確認 11 def logged_in_user 12 # ログインしていないのなら 13 unless logged_in? (解説:sessionにuser.idがあればtureを返す。userがログインしたらuser.idを元にsessionに情報が格納される) 14 store_location 15 flash[:danger] = 'Please log in.' 16 redirect_to login_url 17 end 18 end
rsepcのログをみる限りログインできていないことから、before_actionの logged_in_userによってlogin_urlに飛ばされているのだと思います。
どのようにすればこれのテストを再現することができるのでしょうか?
ちなみに、ブラウザ情では期待している動作になっておりますので、問題はないかと思います。
どんな些細なことでも構いませんので、どなたか教えていただければとても助かります。
よろしくお願いします。
neko_daisukiさんの回答より
test_helperを下記のメソッドを追記
testhelper
1def sign_in(user) 2 allow_any_instance_of(ActionDispatch::Request).to receive(:session).and_return(user_id: user.id) 3 end
usersrequestspec
1subject { response } 2 let(:user) { FactoryBot.create(:user) } 3 # ユーザーがログインしている場合 4 context 'The user is logged in' do 5 before do 6 sign_in(user) ← 修正 7 get edit_user_path(user) 8 end 9 it 'responds successfully' do 10 is_expected.to be_successful 11 end 12 13 it 'returns a 200 response' do 14 is_expected.to have_http_status(200) 15 end 16 end
rspecを実行した結果
しっかりsessionの値を取得しrenderしていることが確認できます。
neko_daisukiさんの記述していただいたコードでは以前と同じログになったため、下記qiitaの記事を参考にしたところ、成功いたしました。
request spec で session 値を設定する
詳しい挙動等についてはこれから調べるため説明することはできませんが、とりあえず動作することができましたので、同じようにつまづいている方の参考になればと思います。
回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2020/12/27 09:43