【devise】rspecでログイン状態を作るためにやるべき3つの手順

  • このエントリーをはてなブックマークに追加

deviseでユーザ認証機能を作り、rspecの中でログインした後の処理をテストしたい時ってありませんか?

例えば、マイページへは、ログインしないとアクセスできないという機能。

このように、「ユーザがログインした後に、何か処理をする」という機能は、WEBサービスを作る時、必ずと言っていいほどでてきます。機能を作るということは、テストコードも必要ですよね。

そこで本日は、僕も実際に使っている手順をご紹介します。

この通りにやって頂くだけで、ログインした状態の処理をテストできるようになります。

環境

・rails 5.0.7

・devise 4.4.3

・rspec-rails 3.7.2

 

1. ログイン処理をまとめたmoduleを作成する。

以下のファイルにログイン処理を記載していきます。ファイル名は自由に付けてもらって大丈夫です。(supportディレクトリがない場合は手動で作成して下さい!)

 

対象ファイル: spec/support/controller_macros.rb

 

module ControllerMacros
  def login_admin
    @request.env["devise.mapping"] = Devise.mappings[:user]
    admin = User.create(email: "admin@admin.com", password: "111111")
    sign_in admin
  end
end

 

それでは、1つ1つ処理を解説していきます。

 

@request.env[“devise.mapping”] = Devise.mappings[:user]

これは、routes.rbの中に記載されている、deviseforのリソースをマッピングするための処理になります。具体的に言うと、後程使用する「signin」などが使用できるようになります。

 

admin = User.create(email: “admin@admin.com“, password: “111111”)

これは、テストで使用する、ログイン用のユーザを作成しています。今回は、deviseの機能を絞っているため、emailとpasswordだけでした。ここは、適宜環境に合わせて頂く必要があります。

 

sign_in admin

これは、作成したユーザでのログイン処理になります。簡単ですね!

 

2. 1で作成したmoduleの読み込み設定を行う。

この作業が本日の山場です。ここを間違えてしまうと、せっかく作成した処理が使用できない、という悲しい状態になります。それでは、気をつけていってみましょう。

 

対象ファイル: spec/rails_helper.rb

 

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

RSpec.configure do |config|
  〜
  config.include ControllerMacros
end

 

やった作業としては、以下の2つ。

  • コメントアウトの解除
  • 1行追加

 

それでは、細かく解説していきます。

 

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

これは、作成したmoduleが格納されたディレクトリ(spec/support/)の配下を読み込む設定です。デフォルトでは、コメントアウトされているため、コメントアウトの解除をする必要があります。

ちなみに処理としては、support配下を1つ1つrequireしているだけです。

 

config.include ControllerMacros

これは、作成したmoduleを読み込むための処理です。今回作成したmoduleは、ControllerMacrosでしたので、読み込んでいます。

 

3. テストコードの中でログイン処理を使う。

それでは、実際にテストコードを書いて行きましょう。

 

テスト対象の概要

  • ログインしないとマイページにアクセスできない。
  • ログインしていない状態で、マイページにアクセスすると、ログインページへリダイレクトされる。

 

テスト対象のコード

 

対象ファイル: config/routes.rb

 

Rails.application.routes.draw do
  devise_for :users
  # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
  root 'like#index'
  get '/mypage', to: 'like#mypage'
end

 

対象ファイル: app/controllers/application_controller.rb

 

class ApplicationController < ActionController::Base
  protect_from_forgery with: :exception

  def after_sign_in_path_for(resource)
    root_path
  end

  private
  def sign_in_required
    redirect_to new_user_session_path unless user_signed_in?
  end
end

 

対象ファイル: app/controllers/like_controller.rb

 

class LikeController < ApplicationController
  before_action :sign_in_required, only: [:mypage]
  def index
  end
  def mypage
  end
end

 

 

テストコード

 

対象ファイル: spec/controllers/likecontrollerspec.rb

 

describe '#mypage' do
    # ログインした状態の処理のテストコード
    context 'When GET with logged in' do
      it 'HTTP status is 200' do
        login_admin
        get :mypage
        expect(response).to have_http_status(200)
      end
    end
   
    # ログインしていない状態のテストコード
    context 'When GET with not logged in' do
      it 'HTTP status is 302' do
        get :mypage
        expect(response).to have_http_status(302)
      end
    end
  end

 

login_adminが、今回作成したログイン処理です。この処理を最初に持ってきてもらうだけで、ログイン状態を作ることができます。とても簡単で使いやすいのではないでしょうか。

 

まとめ

いかがでしたでしょうか。思ったより簡単だ!と思った方もいるのではないでしょうか。僕は、テストで使うための準備で、躓いてしまい少し時間が掛かってしまいました。(笑)

1度作ってしまえば、テストがとても楽になるので是非作ってみて下さい。

GitHub | 今回作成したコード

 

  • このエントリーをはてなブックマークに追加

SNSでもご購読できます。

コメントを残す

*