36
29

More than 3 years have passed since last update.

【Rspec・devise token auth】Rails APIアプリのRspecテストでユーザログイン・認証を実装する方法

Last updated at Posted at 2020-03-24

Rspecテスト内でdevise token authをつかってユーザログイン・認証するのはどうするんだ!?
Deviseのやり方はたくさんあるのですがdevise token authは探すのに苦労したので、私と同じ状況に陥っている方のためにこの記事を残しておきます。

やりたいこと

下記の様に、BooksControllercreateメソッドがあり、createメソッドを実行するにはユーザが認証が必須(authenticate_user!)だとします。

books_controller.rb
class BooksController < ApplicationController
  before_action :authenticate_user!

  def create
    book = Book.new(book_params)

    if book.save
     render json: { status: 'SUCCESS', data: book }
    else
     render json: { status: 'ERROR', data: book.errors }
    end
  end

  def book_params
   params.require(:book).permit(:name, :category, :author, :price)
  end
end

Rspecテストでユーザ認証を実装せずに書くと下記の様な感じになりますが・・・

books_spec.rb
require 'rails_helper'

RSpec.describe 'BooksAPI', type: :request do
  describe 'POST /books/create' do
    it '本を新規登録する' do
      params = {
        book: {
          name: "Rspecがよくわかる本",
          author: "豊田桃子",
          category: "プログラミング",
          price: 1400
        }
      }

      post books_path, params: params
      expect(response).to have_http_status :ok
    end
  end
end

もちろんauthenticate_user!が通らないので、expected the response to have status code :ok (200) but it was :unauthorized (401)というエラーが返ってきます。

BooksAPI
  POST books/create
    本を新規登録する (FAILED - 1)

Failures:

  1) BooksAPI POST books/create 本を新規登録する
     Failure/Error: expect(response).to have_http_status :ok
       expected the response to have status code :ok (200) but it was :unauthorized (401)
     # ./spec/requests/books_spec.rb:17:in `block (3 levels) in <top (required)>'

Finished in 0.14515 seconds (files took 3.38 seconds to load)
1 example, 1 failure

ということでdevise token authを使ってtokenベースで認証を行っている場合のRspecでのテストの書き方を解説したいと思います。

手順

  1. ヘルパーモジュールを作りsign_inメソッドを実装する
  2. ヘルパーモジュールをRspecで読み込む
  3. テストでヘルパーモジュールを使ってsign_inする

ヘルパーモジュールを作りsign_inメソッドを実装する

libディレクトリ直下にauthorization_spec_helper.rbという名前のファイルを作成します。下記のコードを貼り付けます。

lib/authorization_spec_helper.rb
module AuthorizationSpecHelper
  def sign_in(user)
    post "/auth/sign_in/",
      params: { email: user[:email], password: user[:password] },
      as: :json

    response.headers.slice('client', 'access-token', 'uid')
  end
end

userを使ってdevise_token_authのPOSTメソッドにてサインイン後、responseとして返ってきたclientaccess-tokenuidを返すヘルパーメソッドです。

ヘルパーモジュールをRspecで読み込む

ヘルパーモジュールをRspecで使える様にするために下記の一文を追加します。

rails_helper.rb
RSpec.configure do |config|
  # ....
  # ....
  config.include AuthorizationSpecHelper, type: :request
end

テストでヘルパーモジュールを使ってsign_inする

これでヘルパーモジュールを使う準備ができました。あとはbooks_spec.rbを修正していくだけです。

books_spec.rb
require 'rails_helper'

RSpec.describe 'BooksAPI', type: :request do
  describe 'POST books/create' do
    it '本を新規登録する' do
      # 下記の2行を追加する
      # DBに下記user情報のuserが存在している前提
      user = { email: "momoko@test.com", password: "123456" }
      auth_tokens = sign_in(user)

      params = {
        book: {
          name: "Rspecがよくわかる本",
          author: "豊田桃子",
          category: "プログラミング",
          price: 1400  
        }
      }

      # headersを追加
      post books_path, params: params, headers: auth_tokens

      expect(response).to have_http_status :ok
    end
  end
end

これで再度テストを実行してみると・・・・通った!!!

BooksAPI
  POST books/create
    本を新規登録する

Finished in 0.7509 seconds (files took 4.08 seconds to load)
1 example, 0 failures

これでもOK

require 'rails_helper'

RSpec.describe 'BooksAPI', type: :request do
  describe 'POST books/create' do
    let(:user) { { email: "momoko@test.com", password: "123456" } }
    let(:auth_tokens) { sign_in(user) }

    it '本を新規登録する' do
      params = {
        book: {
          name: "Rspecがよくわかる本",
          author: "豊田桃子",
          category: "プログラミング",
          price: 1400  
        }
      }

      post books_path, params: params, headers: auth_tokens

      expect(response).to have_http_status :ok
    end
  end
end

調べるまでが大変でしたが、実装自体はとても簡単でした。お役に立てれば嬉しいです!

36
29
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
36
29