LoginSignup
13
11

More than 3 years have passed since last update.

jwtで認証を実装する時のrspecテスト

Last updated at Posted at 2020-03-21

はじめに

今参加させていただいているスタートアップでapi実装をしており、認証をfirebase authenticationに頼っているのですが、rspecでテストを行うときにjwtの認証をよしなにスキップする方法でめちゃめちゃハマったのでその備忘録です

元々のコード(説明のためかなり省略しています)

applicatioion_controller.rb
class ApplicationController < ActionController::Base
  before_action :authenticate!

  private
  def authenticate!
    if request.headers['Authorization'].present?
      jwt = request.headers['Authorization']
      # jwtを渡すと検証を行いユーザーの情報を返してくれる独自モジュールを呼び出し
      @user_info = Firebase::JwtAuth.authenticate(jwt) 
    else
      render json: { type: '401', message: 'not authorized' }, status: 401
    end
  end
end
user_controller.rb
class UsersController < ApplicationController
  # ユーザー一覧を持ってくる
  def index
    users = User.all
    render json: user status: :ok
  end
end
spec/requests/user_spec.rb
describe UsersController, type: :request do
  let(:headers) { { CONTENT_TYPE: 'application/json', Authorization: 'hoge_token' } }

  describe 'GET /users' do
    it '全てのユーザーを取得する' do
      # header情報をくっつけてリクエストする
      get "/users", headers: headers

      # ステータスコード200が返ってくる、、、はずだった
      expect(response.status).to eq(200)
    end
  end
end

問題点

最初はこんな感じで実装してたのですが、、、これだと色々と問題があります

  • jwtは有効期限が決められているため、実装した瞬間は通ることはあっても一定の時間が経つと通らなくなってしまう
  • テストをするたびにfirebase側に不要なリクエストを送ってしまう

もっとあるとは思いますが、ざっとこんなところでしょうか?

対処法

これの対処法としては
テスト時にauthenticate!メソッドが呼ばれた時はあらかじめ設定しておいた@user_infoを返すようなスタブを作成するというものです

※スタブってなんぞ?って人は↓この辺を見てあとは自分で調べてくださいw
https://wa3.i-3-i.info/word14933.html

ってことなのでそのスタブを作っていきます

/support/authenticated_helper.rb
module AuthenticationHelper
  def authenticate_stub
    # 渡したいインスタンス変数を定義
    @user_info = [
      {
        'name' => 'kosuke',
        'email' => 'kosuke@example.com',
        'email_verified' => true,
      }
    ]

    # allow_any_instance_ofメソッドを使ってauthenticate!メソッドが呼ばれたら
    # ↑のインスタンス変数を返す
    allow_any_instance_of(ApplicationController).to receive(:authenticate!).and_return(@user_info)
  end
end

そして作ったスタブをテストコードから呼び出します

spec/requests/user_spec.rb
describe UsersController, type: :request do
  let(:headers) { { CONTENT_TYPE: 'application/json', Authorization: 'hoge_token' } }

  describe 'GET /users' do
    it '全てのユーザーを取得する' do
      authenticate_stub # ←追記

      # header情報をくっつけてリクエストする
      get "/users", headers: headers

      # ステータスコード200が返ってくる
      expect(response.status).to eq(200)
    end
  end
end

こうしてあげることでauthenticate!メソッドが呼ばれた時に用意しておいたインスタンス変数が帰るので
無事テストを通すことができます

以上!

13
11
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
13
11