前提
- deviseをインストールしておきましょう。
- userモデル(deviseの対象モデル)を作成しておくこと。
事前準備
rspec関連Gemのインストール
Gemfile
1 2 3 4 5 6 |
group :development, :test do gem 'rspec-rails', '~> 4.0.1' gem 'shoulda-matchers', '~> 4.4.1', require: false gem 'factory_bot_rails', '~> 6.1.0' gem 'rails-controller-testing' end |
インストール
1 |
bin/rails g rspec:install |
rails_helper.rb
コメントアウトの解除
1 |
Dir[Rails.root.join('spec/support/**/*.rb')].sort.each { |f| require f } |
FactoryBotのリロード(これをしないとFactoryBotが動かない場合があります。)
1 2 3 4 |
RSpec.configure do |config| config.before(:all) do FactoryBot.reload end |
spec/support/factory_bot.rb
1 2 3 4 5 |
require 'factory_bot' RSpec.configure do |config| config.include FactoryBot::Syntax::Methods end |
shoulda_matchers.rb
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
require 'shoulda/matchers' Shoulda::Matchers.configure do |config| config.integrate do |with| with.test_framework :rspec with.library :rails end end module Shoulda module Matchers module ActionController class RouteParams protected def normalize_values(hash) hash end end end end end RSpec.configure do |config| config.include Shoulda::Matchers::ActiveModel, type: :form end |
devise関連の設定
sessions_controller.rb
1 2 3 4 5 6 7 8 9 10 11 |
module Devise module Users class SessionsController < Devise::SessionsController protected def after_sign_in_path_for(user) root_path end end end end |
routes.rb
1 |
root to: 'tests#index' |
テストデータの作成(FactoryBot)
1 2 3 4 5 6 |
FactoryBot.define do factory :user do sequence(:email) { |n| "test#{n}@example.com" } sequence(:password) { |n| "password#{n}" } end end |
実装
ログイン用モジュールの作成
1 2 3 4 5 6 7 8 9 10 |
module ControllerMacros def login_user(user = create(:user)) @request.env['devise.mapping'] = Devise.mappings[:user] sign_in user end end RSpec.configure do |config| config.include Devise::Test::ControllerHelpers, type: :controller config.include ControllerMacros, type: :controller end |
@request.env['devise.mapping'] = Devise.mappings[:user]
deviseを継承したコントローラーのテストを行いたい場合はこちらの宣言を必ず利用する必要があります。rspecはrouterを使わないのですが、deviseはrouterから情報を受け取っているので明示する必要があるためです。上記の例ではrouterのuser scopeを使えるようにしています。
session_controller_spec.rb
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
require 'rails_helper' RSpec.describe Devise::Users::SessionsController, type: :controller do describe 'GET new' do it 'ログイン時' do login_user get :new # response is_expected.to respond_with(:redirect) is_expected.to redirect_to(root_path) end end end |
用意すると望ましいテストケース
- ログイン時にログイン画面(session#new)に遷移しようとしたらリダイレクトされるか。
- ログアウト時にログイン画面(session#new)に遷移しようとしたらログイン画面が表示されるか。
- ログイン時にユーザーを作成(session#create)しようとしたらログイン画面にリダイレクトされるか。
- ログアウト時にユーザーを作成(session#create)しようとしたら登録ができているか、また登録後ログイン画面にリダイレクトされるか。
- ログアウト時に不正な入力値(パスワードがない)場合に登録画面にリダイレクトされるか。
- ログイン時にログアウト(DELETEメソッド実行)をしたらログイン画面が表示されるか。
- 非ログイン時にログアウト(DELETEメソッド実行)をしたらログイン画面が表示されるか。
-
after_sign_in_path_forをsendメソッドとかで直接呼んでログイン画面が表示されるか。
この記事へのコメントはありません。