質問をすることでしか得られない、回答やアドバイスがある。

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

新規登録して質問してみよう
ただいま回答率
85.35%
Ruby on Rails 5

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

RSpec

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

Q&A

解決済

1回答

2863閲覧

RSpecでセッションのDESTROY(DELETE)テストがしたいです。

退会済みユーザー

退会済みユーザー

総合スコア0

Ruby on Rails 5

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

RSpec

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

0グッド

0クリップ

投稿2021/02/11 04:54

編集2021/02/11 04:57

##実現したいこと
sessionの情報の扱っている動作の実現してログアウトを再現したいです。
処理の流れとしては、
ログイン状態でログアウトを実行した場合、
セッション情報を削除してログイン画面に戻ります。

お手数をかけて申し訳ございませんが、
わかる方がおられたらどうか、
対処法のヒントでもいいのでお教えをお願い致します。
##前提
ログイン用のテストは全て通過しております(GREEN)。
ログアウトのテスト部分の行からテストを行っております。
##発生している問題・エラーメッセージ
#####エラーメッセージ

Run options: include {:locations=>{"./spec/controllers/sessions_controller_spec.rb"=>[48]}} FF Failures: 1) SessionsController sessions#destroy ログアウトした場合 セッション情報が削除されること Failure/Error: expect(@user).to eq nil expected: nil got: #<User id: 1, name: "testuser", password_digest: "$2a$04$vDsfCC2abKzIWoBqXqOYbO/WMDqZI1iCUVq50ss.RCy...", created_at: nil, updated_at: nil, birthday: nil> (compared using ==) # ./spec/controllers/sessions_controller_spec.rb:56:in `block (4 levels) in <top (required)>' 2) SessionsController sessions#destroy ログアウトした場合 ログインページに戻ること Failure/Error: expect(response).to redirect_to(root_path) Expected response to be a <3XX: redirect>, but was a <200: OK> Response body: # ./spec/controllers/sessions_controller_spec.rb:60:in `block (4 levels) in <top (required)>' Finished in 0.26175 seconds (files took 9.14 seconds to load) 2 examples, 2 failures Failed examples: rspec ./spec/controllers/sessions_controller_spec.rb:54 # SessionsController sessions#destroy ログアウトした場合 セッション情報が削除されること rspec ./spec/controllers/sessions_controller_spec.rb:59 # SessionsController sessions#destroy ログアウトした場合 ログインページに戻ること

##該当のソースコード
#####sessions_controller_spec.rb[テストコード]

RSpec.describe SessionsController, type: :controller do describe 'sessions#create' do context 'ログインが成功した場合' do before do @user = FactoryBot.build(:user) post(:create, params: { session: { id: @user.id, name: @user.name, password: @user.password } }) end it 'ユーザー名が同じであること' do expect(@user.name).to eq 'testuser' end it 'passwordが同じであること' do expect(@user.password).to eq 'password' end it 'マイページにリダイレクトされること' do expect(response).to redirect_to(mypage_path) end end context 'ログインを失敗した場合' do before do @user = FactoryBot.build(:user) post(:create, params: { session: { id: @user.id, name: 'error', password: @user.password } }) end it 'ログインページにリダイレクトされること' do expect(response).to render_template 'home/index' end end end describe 'sessions#destroy' do context 'ログアウトした場合' do before do @user = FactoryBot.build(:user) end it 'セッション情報が削除されること' do delete :destroy expect(@user).to eq nil end it 'ログインページに戻ること' do expect(response).to redirect_to(root_path) end end end end

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

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

#####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

##試したこと
下記のコードで実施しましたが、セッションしたユーザーのデータが残っておりました。

その1 delete(:destroy, params: { session: { id: @user.id, name: 'error', password: @user.password } })

・検索でRSpec DELETEで検索した内容を実施するも失敗
https://stackoverflow.com/questions/25496103/delete-an-object-in-rspec-rails
##補足情報(FW/ツールのバージョンなど)
[作業環境]
macOS BigSur 11.2
Docker 20.10
Ruby 2.4.5
Rails 5.2.2
RSpec 3.9.0

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

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

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

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

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

guest

回答1

0

ベストアンサー

こんばんは。前回こちらの質問をされた方でしょうか?
https://teratail.com/questions/321532

セッション情報の削除とは

ぱっと見て、問題点が2つあります。

1つ目は、セッション情報の削除について。

セッション情報を削除してログイン画面に戻ります。

とありますが、テストでは

expect(@user).to eq nil

と書いてありますね。
ここでいう @user は、「セッション情報」ではなくて、データベースに登録されたユーザのデータそのものになります。

セッション情報のdelete = データベースに登録されたユーザデータの削除、ではないはずですよね?
(もしそうだとすると、毎回サインアップしないといけません)

ここで確認すべきテストは、SessionsController#deleteメソッドでセッション情報からuser_idが削除されて、ログアウト状態になったこと、であって、該当のユーザデータが削除されたことではありません。

2つめですが、「ログアウトしたことをテストする」ためには、前提としてログインしている必要があります。

describe 'sessions#create' do ...end のところではログインさせていますが、describe 'sessions#destroy' do ..end の部分はまた独立したテストになっているので、「ログアウト」を試そうとしてもそもそもログインしていない場合はリダイレクトの確認ができません。

一旦、「セッション情報が削除されること」の部分を直してみるとこんな感じです。
おそらく「ログインページに戻ること」は失敗すると思います。いかがでしょう。

ruby

1 2 describe 'sessions#destroy' do 3 context 'ログアウトした場合' do 4 before do 5 @user = FactoryBot.build(:user) 6 end 7 8 it 'セッション情報が削除されること' do 9 delete :destroy 10 11 # ひとまずsession.delete(:user_id)されてるので、 12 # ここはsession[:user_id]がnilのはずというテストにする 13 expect(session[:user_id]).to eq nil 14 end 15 16 it 'ログインページに戻ること' do 17 # この状態では、多分ここはまだ失敗すると思います(先にログインが必要) 18 expect(response).to redirect_to(root_path) 19 end 20 end 21 end 22

備考: Factoryの確認

ログインのテストは全て通ったとのことですが、

@user = FactoryBot.build(:user)

とありますが、この状態でテストは通ってるとのことですが、間違いないですか?

@user = FactoryBot.create(:user) でないと通常はテストは通らないと思うので、ちょっと気になっています。

users.rb (Factory)にidが入っているので、どんなケースでもid: 1のユーザを対象にしているんですね。
もしかしたら、テストを走らせているデータベースには、必ずUserID: 1のデータが入っているのかな?
この辺も気になりつつ...。

なお、コントローラ自体は問題ない気がします。
その「動作が正しいのかのテスト」は、書き方に慣れたり、別のドキュメントを参考にしないとわかりにくい点も多いので、少しずつ進めていくのが良いと思います。

投稿2021/02/11 10:00

編集2021/02/11 11:57
suama

総合スコア1997

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

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

退会済みユーザー

退会済みユーザー

2021/02/12 07:30 編集

suama 様 おしゃる通り、前回もお世話になりました。 お忙しい中、今回もご回答していただき、 ありがとうございます。 セッションのログアウトでのおしゃる通り、 オブジェクト自身の削除で可能かと検証をしておる所が間違いでした。 ご指摘通り。本来のログイン状態の再現の記述で成功致しました。 [訂正コード] describe 'sessions#destroy' do  context 'ログアウトした場合' do   before do    @user = FactoryBot.build(:user)    post(:create, params: {     session: {     id: @user.id,     name: @user.name,     password: @user.password     }    })   end   it 'セッション情報が削除され、ログインページに戻ること' do    delete :destroy    expect(session[:user_id]).to eq nil    expect(response).to redirect_to(root_path)   end  end end また、備考: Factoryの確認の件ですが、 テストデータはすでに登録しております。 それを使用して現在テストしております。 最後に、 備考の最後の行にアドバイスを記述して頂きありがとうございました。
suama

2021/02/12 08:38

> テストデータはすでに登録しております。 なるほど、ありがとうございます! いつも手元でのテストの時は、データベースからデータを消してクリーンな状態で行ったりするので、「あれ、buildなんだ」と思ってしまいました。失礼しました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問