前提・実現したいこと
Ruby on Railsでgemを使わずにsessionでログイン機能を作りました。
ログイン後しか行けないページにログイン後なら行けることをテストしたいのですが、
テストコード内でsessionを維持できず、ログイン後の状態を作れません。
発生している問題・エラーメッセージ
F Failure: UsersControllerTest#test_should_get_index [/Users/matsumurakouji/workspace/buying_app/test/controllers/users_controller_test.rb:19]: Expected response to be a <2XX: success>, but was a <302: Found> redirect to <http://www.example.com/login> Response body: <html><body>You are being <a href="http://www.example.com/login">redirected</a>.</body></html>
該当のソースコード
test
1require 'test_helper' 2 3class UsersControllerTest < ActionDispatch::IntegrationTest 4 5 test "should get index" do 6 session = {'user_id' => 1} 7 session[:user_id] = 1 # この2行が両方ないと1つ目のテストに通りません 8 # このコードはsessionをただの変数名として扱っているコードと思っています 9 #add_session(session) # undefined method `add_session' 10 #@user_one = users(:user_one) 11 #post '/login', params: { user: { email: @user_one.email, password: @user_one.password_digest } } 12 get '/users/index' # ログイン後しか行けないページです。 13 assert_equal 1, session[:user_id] # このテストは通ります 14 assert_response :success # このテストで上記のFailureになります 15 # controllerのauthenticate_userをコメントアウトすると通ります 16 end 17 18 test "should get login" do 19 get "/login" 20 assert_response :success 21 end #"/login"はログインしなくても行けるページで、このテストは通ります
fixture
1user_one: 2 id: 1 3 name: asd 4 email: qwe@rty 5 password_digest: uiop
controller
1class UsersController < ApplicationController 2 before_action :set_current_user 3 before_action :authenticate_user,{only:[:index]} 4 5 def set_current_user 6 @current_user = User.find_by(id: session[:user_id]) 7 end 8 9 def authenticate_user 10 if @current_user == nil 11 flash[:notice] = "ログインが必要です" 12 redirect_to("/login") 13 end 14 end 15 16 17 18 def login_form 19 end 20 21 def login 22 @user = User.find_by(email: params[:email]) 23 if @user && @user.authenticate(params[:password]) 24 session[:user_id] = @user.id 25 flash[:notice] = "ログインしました" 26 redirect_to("/posts/index") 27 else 28 @error_message = "メールアドレスまたはパスワードが間違っています" 29 @email = params[:email] 30 @password = params[:password] 31 render("users/login_form") 32 end 33 end 34 35 def index 36 @users=User.all 37 end 38 39 40 41
routes
1Rails.application.routes.draw do 2 get "users/index" => "users#index" 3 get "login" => "users#login_form" 4 post "login" => "users#login" 5end
試したこと
・手動では正常に動作する(ログインした後のみ"/users/index"に行ける)ことは確認しました
・testのコメントアウトしている場所にadd_session(session)を入れると「undefined method `add_session'」というエラーメッセージが出ます
・testの@user_oneから始まる行とpost "/login"から始まる行に関しては、fixtureと同じデータを登録しているにも関わらずテストコードではuserデータを取得できませんでした(webページからのログインでは、そのuserでできました)
・Failureメッセージは、sessionが保持できなかったためにcontrollerのauthenticate_userに引っかかってしまったことが原因であることは分かっています
補足情報(FW/ツールのバージョンなど)
Ruby 2.5.0(少し古いバージョンを使用しています)
Rails 5.2.3
あなたの回答
tips
プレビュー