Rspecテスト内でdevise token auth
をつかってユーザログイン・認証するのはどうするんだ!?
Devise
のやり方はたくさんあるのですがdevise token auth
は探すのに苦労したので、私と同じ状況に陥っている方のためにこの記事を残しておきます。
やりたいこと
下記の様に、BooksController
にcreate
メソッドがあり、create
メソッドを実行するにはユーザが認証が必須(authenticate_user!
)だとします。
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テストでユーザ認証を実装せずに書くと下記の様な感じになりますが・・・
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でのテストの書き方を解説したいと思います。
手順
- ヘルパーモジュールを作り
sign_in
メソッドを実装する - ヘルパーモジュールをRspecで読み込む
- テストでヘルパーモジュールを使って
sign_in
する
ヘルパーモジュールを作りsign_in
メソッドを実装する
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として返ってきたclient
、access-token
、uid
を返すヘルパーメソッドです。
ヘルパーモジュールをRspecで読み込む
ヘルパーモジュールをRspecで使える様にするために下記の一文を追加します。
RSpec.configure do |config|
# ....
# ....
config.include AuthorizationSpecHelper, type: :request
end
テストでヘルパーモジュールを使ってsign_in
する
これでヘルパーモジュールを使う準備ができました。あとは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
調べるまでが大変でしたが、実装自体はとても簡単でした。お役に立てれば嬉しいです!