🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
RSpec

RSpecはRuby用のBDD(behaviour-driven development)フレームワークです。

Ruby on Rails

Ruby on Railsは、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

Q&A

解決済

1回答

3589閲覧

RSpecでログインのテストを実施

退会済みユーザー

退会済みユーザー

総合スコア0

RSpec

RSpecはRuby用のBDD(behaviour-driven development)フレームワークです。

Ruby on Rails

Ruby on Railsは、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

0グッド

0クリップ

投稿2021/02/09 11:03

編集2021/02/09 11:07

前提・実現したいこと

RSpecでログインのテストを実現したいです。
sessionの情報の扱っている動作の実現してログインを再現したいです。

発生している問題・エラーメッセージ

エラーメッセージ SessionsController sessions#create ログインが成功した場合 ユーザー名が同じであること (FAILED - 1) passwordが同じであること (FAILED - 2) マイページにリダイレクトされること (FAILED - 3) Failures: 1) SessionsController sessions#create ログインが成功した場合 ユーザー名が同じであること Failure/Error: post login_path, params: { session: { id: @user.id, name: @user.name, password: @user.password } } ActionController::UrlGenerationError: No route matches {:action=>"/login", :controller=>"sessions",:session=>{:id=>1, :name=>"testuser",:password=>"password"}} /usr/local/bundle/gems/rails-controller-testing-1.0.5/lib/rails/controller/testing/template_assertions.rb:62:in `process /usr/local/bundle/gems/rails-controller-testing-1.0.5/lib/rails/controller/testing/integration.rb:16:in block (2 levels) in <module:Integration> ./spec/controllers/sessions_controller_spec.rb:6:in `block (2 levels) in <top (required)>'

該当のソースコード

sessions_controller.rb[テスト対象]

class SessionsController < ApplicationController def create user = User.find_by(name: params[:session][:name]) if user && user.authenticate(params[:session][:password]) session[:user_id] = user.id redirect_to mypage_path else render 'home/index' end end def destroy session.delete(:user_id) redirect_to root_path end end

sessions_controller_spec.rb[テストコード]

require 'rails_helper' RSpec.describe SessionsController, type: :controller do before do @user = FactoryBot.build(:user) post login_path, params: { session: { id: @user.id, name: @user.name, password: @user.password } } end describe 'sessions#create' do context "ログインが成功した場合" do it 'ユーザー名が同じであること' do expect(@user.name).to eq 'testuser' end it 'passwordが同じであること' do expect(@user.password).to eq 'password' end it 'マイページにリダイレクトされること' do expect(post :create, params: params).to redirect_to(mypage_path) end end end end

users.rb[セッション情報のモック]

FactoryBot.define do factory :user do id { 1 } name { "testuser" } password{ "password" } end end

試したこと

テストデータの作成をFactoryBotを使用してセッション情報の再現。
⇨ハッシュをうまく再現できていないため、URLが生成されない。
before部分に、post: createを記述。
⇨失敗。
require 'sessions_controller'を追記
⇨同じ内容のエラーメッセージで失敗。

補足情報(FW/ツールのバージョンなど)

[作業環境]
macOS BigSur 11.2
Ruby 2.4.5
Rails 5.2.2
RSpec 3.9.0

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

suama

2021/02/09 14:05 編集

エラーメッセージに、"No route matches {:action=>"/login", :controller=>"sessions" とあるので、ルーティングが適切でないんじゃないかと思います。 期待している処理は、SessionsController#create でしょうか。 rails routes の結果を質問の欄に添えていただけますか? そこに "login_path" が出てこないか、メソッドがPOSTでなければ設定の問題かなと思いますので。 関連: https://teratail.com/questions/321118
退会済みユーザー

退会済みユーザー

2021/02/09 14:10

ご依頼ありがとうございます。 ご指示の通りに、試してみます。
oakbow

2021/02/09 14:22

直すのはこのエラーが解消した後でいいと思いますが、 @user = FactoryBot.build(:user) は動かないですね。 @user = FactoryBot.create(:user) にしてDBに保存させる必要があります。
退会済みユーザー

退会済みユーザー

2021/02/09 14:31 編集

suama様 先にrails routes の結果を貼り付けておきます。 mypage GET /mypage(.:format) users#me login POST /login(.:format) sessions#create logout DELETE /logout(.:format) sessions#destroy root GET / home#index users POST /users(.:format) users#create new_user GET /users/new(.:format) users#new boards GET /boards(.:format) boards#index POST /boards(.:format) boards#create new_board GET /boards/new(.:format) boards#new edit_board GET /boards/:id/edit(.:format) boards#edit board GET /boards/:id(.:format) boards#show PATCH /boards/:id(.:format) boards#update PUT /boards/:id(.:format) boards#update DELETE /boards/:id(.:format) boards#destroy comments POST /comments(.:format) comments#create comment DELETE /comments/:id(.:format) comments#destroy 引続きご紹介して頂いた関連URLの内容を試してみます。 よろしくお願い致します。
suama

2021/02/09 14:55

ありがとうございます! > RSpec.describe SessionsController, type: :controller の指定があるので、 sessions_controller_spec.rb のところで、"post login_path" ではなくて、"post :create" が良いかも。 ちょっと試してみていただけますか? だめだったら、回答側に確認点を書きます。 また、Factoryのところは、oakbowさんが書かれたとおり buildではなくて create が良さそうです。 テスト用のユーザがデータベースに作成されないので、存在しないユーザでのログインになってしまいます。
退会済みユーザー

退会済みユーザー

2021/02/09 14:59

oakbow様 ご助言ありがとうございます。 早速、取り入れてみます。
退会済みユーザー

退会済みユーザー

2021/02/09 15:18 編集

suama様 ご返信ありがとうございます。 ご助言通りに実行したところ、進展致しました。 [ターミナルに表示された結果] SessionsController sessions#create ログインが成功した場合 ユーザー名が同じであること passwordが同じであること マイページにリダイレクトされること (FAILED - 1) Failures: 1) SessionsController sessions#create ログインが成功した場合 マイページにリダイレクトされること Failure/Error: expect(post :create, params: params).to redirect_to(mypage_path) NameError: undefined local variable or method `params' for #<RSpec::ExampleGroups::SessionsController::SessionsCreate::Nested:0x000055a6c4490d48> # ./spec/controllers/sessions_controller_spec.rb:26:in `block (4 levels) in <top (required)>'
suama

2021/02/09 15:16

これは書き方の問題のようですね^^ paramsが変数になっているのですが、ここが26行目では「この変数どこからきてるの?」になっています。 直してみたのを添えますので、ちょっと考えてみてくださいね。
退会済みユーザー

退会済みユーザー

2021/02/09 15:19

はい、かしこまりました! ありがとうございます。
guest

回答1

0

ベストアンサー

こんばんは。質問でのやりとり、ありがとうございます!

ちょっと直してみました。
oakbowさんのご指摘の通り、Factoryもcreateが前提です。

ちなみに、「ユーザー名が同じであること」「passwordが同じであること」の箇所はあまり意味がないかもしれません。
Factoryで作成したユーザには、FactoryBotで指定した値がデフォルトで入るので、コントローラへのアクセス関係なく、変更は特にないためです。

手元で環境があるわけではないのですが、いかがでしょうか。

ruby

1require 'rails_helper' 2 3RSpec.describe SessionsController, type: :controller do 4 before do 5 # ユーザを作成する (buildでなくcreate) 6 @user = FactoryBot.create(:user) 7 8 # 各 it ... do ... end の前に、SessionsController#createにPOSTでリクエストを発行 9 # login_path じゃなくて コントローラのメソッドを記載 (:create) 10 post :create, params: { 11 session: { 12 id: @user.id, 13 name: @user.name, 14 password: @user.password 15 } 16 } 17 end 18 19 describe 'sessions#create' do 20 context "ログインが成功した場合" do 21 it 'ユーザー名が同じであること' do 22 # ここは実際は意味がないかも 23 expect(@user.name).to eq 'testuser' 24 end 25 26 it 'passwordが同じであること' do 27 # ここも実際は意味がないかも 28 expect(@user.password).to eq 'password' 29 end 30 31 it 'マイページにリダイレクトされること' do 32 # ここでもう一回 post :create... をするのはムダなので、before ... でアクセス 33 # エラーになったのは、ここの params がどこから渡ってきた変数なのかわからないため 34 # また、post :create... の結果は、response オブジェクトで取得できるので、そちらで確認 35 # expect(post :create, params: params).to redirect_to(mypage_path) 36 37 expect(response).to redirect_to(mypage_path) 38 end 39 end 40 end 41end

投稿2021/02/09 15:27

suama

総合スコア1997

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2021/02/09 15:58

suama様 ありがとうございます。 無事にテストが通り、実際の動きの再現ができました。 本当に遅くまでお付き合いいただきありがとうございます!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.36%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問