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を呼び出せるように設定
RSpec.configure do |config|
#色々書いてある下に下記行を追記
config.include Devise::Test::IntegrationHelpers, type: :request
end
specからrails_helperを通してDeviseのsigin_in等のヘルパー機能を呼び出せるようになります。
posts_controllerの設定
class PostsController < ApplicationController
自動生成されたbefore_actionがありますが、今回は下記のように修正
before_action :authenticate_user!, expect: [:index]
#省略
end
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実施時に認証用モデルを都度作成することで、簡易に実現できます。
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ディレクトリを作成し下記のファイルを作成
RSpec.configure do |config|
config.include FactoryBot::Syntax::Methods
end
併せて、下記ファイルのコメントアウトを削除し有効にします。
Dir[Rails.root.join('spec', 'support', '**', '*.rb')].each { |f| require f }
テスト用modelを作成します。
FactoryBot.define do
factory :user do
email { "test@test.com"}
#下記の値は同じになるようにしてください
password { "password" }
password_confirmation { "password"}
end
end
specでfactoryを利用して認証ユーザーを取り出すようにします。
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利用