Help us understand the problem. What is going on with this article?

Request SpecでDeviseのsing_in userを実施する

Request specでDeviseのsign_inを実施する

検索するとModuleを利用したものや、認証用モデル作成としてFactory-girlを利用したやや複雑かつやや古いものが多く、少し困ったため
Rails6環境での実施を記録します。

実施環境

  • Rails 6.0.2.2
  • Factory-bot-rails 5.1.1
  • Devise 4.7.1
  • RSpec 3.9

下記を実施して、devise用ユーザーとpostモデルを作成しておきます。

rails generate devise user
rails generate scaffold post body:string

migrateも忘れずに

rails db:migrate

spec実施時に、Deviseのhelperを呼び出せるように設定

spec/rails_helper.rb
RSpec.configure do |config|
  #色々書いてある下に下記行を追記
  config.include Devise::Test::IntegrationHelpers, type: :request
end

specからrails_helperを通してDeviseのsigin_in等のヘルパー機能を呼び出せるようになります。

posts_controllerの設定

app/controller/posts_controller.rb
class PostsController < ApplicationController
  自動生成されたbefore_actionがありますが、今回は下記のように修正
  before_action :authenticate_user!, expect: [:index]
#省略
end
app/config/routes.rb
Rails.application.routes.draw do
  devise_for :users #先頭にくるようにしてください
  resources :posts
  # For details on the DSL available within this file, see https://guides.rubyonrails.org/routing.html
end

認証処理なしで一度spec(自動生成されています)を実行

rspec spec/requests/posts_spec.rb
Failures:

  1) Posts GET /posts works! (now write some real specs)
     Failure/Error: expect(response).to have_http_status(200)
       expected the response to have status code 200 but it was 302
     # ./spec/requests/posts_spec.rb:7:in `block (3 levels) in <main>'

Finished in 0.19729 seconds (files took 3.08 seconds to load)
1 examples, 1 failure

Failed examples:

rspec ./spec/requests/posts_spec.rb:5 # Posts GET /posts works! (now write some real specs)

失敗の内容から、レスポンスステータス200を期待した結果302(ログイン画面へのredirect)が返却され失敗となっています。

factory_Bot未使用の簡易な実装

spec実施時に認証用モデルを都度作成することで、簡易に実現できます。

spec/requests/posts_spec.rb
require 'rails_helper'

RSpec.describe "Posts", type: :request do
  describe "GET /posts" do
    before do
      #認証ユーザーを作成します。
      #各変数の中身は何でも良いです。passwordとpassword_confirmationが一致することだけ確認してください。
      @user = User.create(email: 'test@test.com', password: "password", password_confirmation: "password")
    end

    it "works! (now write some real specs)" do
      #認証処理を行います
      sign_in @user
      get posts_path
      expect(response).to have_http_status(200)
    end
  end
end

非常に簡易ですが、これだけでDevise認証を必要とするspecの作成は可能です。

実行結果

Finished in 0.12959 seconds (files took 1.07 seconds to load)
1 example, 0 failures

factory_botを利用したDevise認証

fixturesのデファクトであるfactory_bot(旧factory_girl)を利用した実装です。

factory_bot利用できるように設定

spec配下にsupportディレクトリを作成し下記のファイルを作成

spec/support/factory_bot.rb
RSpec.configure do |config|
  config.include FactoryBot::Syntax::Methods
end

併せて、下記ファイルのコメントアウトを削除し有効にします。

spec/rails_helper.rb
Dir[Rails.root.join('spec', 'support', '**', '*.rb')].each { |f| require f }

テスト用modelを作成します。

spec/factories/users.rb
FactoryBot.define do
  factory :user do
   email { "test@test.com"}
   #下記の値は同じになるようにしてください
   password { "password" }
   password_confirmation { "password"}
  end
end

specでfactoryを利用して認証ユーザーを取り出すようにします。

spec/requests/posts_spec.rb
require 'rails_helper'

RSpec.describe "Posts", type: :request do
  describe "GET /posts" do
    before do
      #factory_botを利用して認証モデルを作成します。
      @user = create(:user)
    end

    it "works! (now write some real specs)" do
      #認証処理を行います
      sign_in @user
      get posts_path
      expect(response).to have_http_status(200)
    end
  end
end

実行結果

Finished in 0.11056 seconds (files took 1.28 seconds to load)
1 example, 0 failures

サンプルコード

各verのサンプルコードはgithubへ上げてありますのでご参考までに。
factory_bot未使用
factory_bot利用

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away