12
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

deviseの機能をRspecでテストする

Posted at

はじめに

既存Railsアプリにdeviseを導入した際に,
もともとあったRspecのテストを通すために苦労したので書いていきます。


バージョン

rails  : 6.1.1
ruby   : 2.6.6
devise : 4.7.3

原因

私がハマった原因は

  • deviseのテストヘルパーを使うための設定に関する記述が間違っていたこと
  • deviseのユーザー認証の仕組みをきちんと理解していなかったこと

です。


公式READMEのTest helpersの欄にもある通り、
deviseではtestで使える簡単にログイン・ログアウトができるヘルパーがあります。
書いてあるとおり、使えるようにするにはspec/rails_helper.rbに以下の記述をします。

spec/rails_helper.rb
RSpec.configure do |config|
  config.include Devise::Test::ControllerHelpers, type: :controller
  config.include Devise::Test::ControllerHelpers, type: :view
end

使い方はこんな感じ

spec/requests/users_spec.rb
require 'rails_helper'
RSpec.describe "Users" do
  it "ログインしてる時、ユーザーの詳細ページにアクセスできる" do
    user = create(:user)  
    sign_in user
    get users_path
    expect(response).to have_http_status(200)
  end
end

私はこれでtestのどこでもヘルパーが使えるようになると思っていたので、
何回やっても失敗するテストをみて首をかしげていました。

解決手順①

このヘルパーを上記のようなrequestテストでも本当に使えるようにはspec/rails_helper.rbに以下の記述を追加します。

spec/rails_helper.rb
RSpec.configure do |config|
  config.include Devise::Test::IntegrationHelpers, type: :request   #追加
  config.include Devise::Test::ControllerHelpers, type: :controller
  config.include Devise::Test::ControllerHelpers, type: :view
end

これでまずヘルパーがちゃんと使えるようになりました。
が、私の場合はこれだけではまだダメでした。


失敗したテストの内容とエラーをみてみます。

  • テスト
require 'rails_helper'

RSpec.describe "Users" do

  let! (:user)  { create(:user) }
  let! (:user2) { create(:user) }

  describe '#edit' do
    context '本人ではない場合' do
      befor do  
        sign_in user2
        get edit_user_path user
      end
      it 'Homeにリダイレクトされる' do
        expect(response).to redirect_to root_path
      end
    end
  end
end
  • エラー
Failure/Error: expect(response).to redirect_to root_path
     
       Expected response to be a redirect to <http://www.example.com/> but was a redirect to <http://www.example.com/users/sign_in>.
       Expected "http://www.example.com/" to be === "http://www.example.com/users/sign_in".

本人ではないユーザーがユーザー情報編集ページにアクセスすると、
Homeにリダイレクトされるということを確認するテストです。
エラーは、期待していたhttp://www.example.com/ではなく、
http://www.example.com/users/sign_inにリダイレクトされていますよ、と伝えています。
何故か。ログインページにリダイレクトされています。

解決手順②

原因はFactorybotの設定にありました。
今回はdeviseのconfirmableという
「ユーザー登録時に認証メールを送信し、メールに記載されているリンクにアクセスすることで本登録完了」
といった感じのよくある機能を提供してくれるモジュールを使用していました。
この機能は、ユーザーがメールのリンクにアクセスした時confirmed_atというカラムに認証の日時を保存し、その有無で機能へのアクセスを制限するというものです。
テストが通らなかった時のFactorybotの設定はこうでした。

spec/factories/users.rb
FactoryBot.define do
  factory :user do
    name { "test_user" }
    sequence(:email) { |n| "test#{n}@exmple.com" }
    password { "password" }
    password_confirmation { "password" }
  end
end

confirmed_atカラムに関する記述がありません、これに書き加えます。

spec/factories/users.rb
FactoryBot.define do
  factory :user do
    name { "test_user" }
    sequence(:email) { |n| "test#{n}@exmple.com" }
    password { "password" }
    password_confirmation { "password" }
    confirmed_at { Date.today }  ##追加
  end
end

これでテストが通るようになりました。
deviseに対する理解が全く足りていませんでした。
当たり前のことですが、使う前にきちんとREADMEなどを読み込んでおく事が重要だと身にしみました。


以上です。ありがとうございました。


参考記事

How To: sign in and out a user in Request type specs
devise


12
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
12
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?