こんばんは
QiitaでRspec/devise_token_authで調べて出てきたのを参考に認証が通った状態でpostができるかのテストをしてみたところ、詰まったのでここに書き残しておきます
認証エラーの起きたテストコード
authorization_spec_helper.rb
module AuthorizationSpecHelper
def sign_in(user)
post api_v1_user_session_path,
params: { email: user[:email], password: user[:password] },
as: :json
response.headers.slice('client', 'access-token', 'uid')
end
end
まずQiitaの記事を参考に、サインインしたときにレスポンスのclient,access-token,uidを切り取ってくれるヘルパーメソッドを作成します。
posts_spec.rb
require 'rails_helper'
RSpec.describe 'PostsAPI', type: :request do
describe 'POST posts/create' do
it '投稿を新規登録する' do
user = { email: 'test@example.com', password: 'test2525' }
auth_tokens = sign_in(user)
params = { post: { title: 'hogehoge', content: 'foofoo' } }
post api_v1_auth_posts_path, params: params, headers: auth_tokens
expect(response).to have_http_status :ok
end
end
end
そして上記のテストを実行すると
Terminal
Failures:
1) PostsAPI POST posts/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/v1/auth/posts_spec.rb:10:in `block (3 levels) in <main>'
Finished in 0.36107 seconds (files took 4.26 seconds to load)
3 examples, 1 failure
認証エラーになります。
解決策
まずテストが通ったコードを貼っておきます。
require 'rails_helper'
RSpec.describe 'PostsAPI', type: :request do
describe 'POST posts/create' do
it '投稿を新規登録する' do
# user = { name: 'test', email: 'test@example.com', password: 'test2525' }
client_user = create(:user)
# auth_tokens = sign_in(user)
auth_tokens = client_user.create_new_auth_token
params = { post: { title: 'hogehoge', content: 'foofoo' } }
post api_v1_auth_posts_path, params: params, headers: auth_tokens
expect(response).to have_http_status :ok
end
end
end
-
client_user = create(:user)
とはclient_user = FactoryBot.create(:user)
の省略型です。つまりFactoryBotを用いてあらかじめ作成してあるuserをここで呼び出しています。そしてcreateメソッドで新規作成&DBに保存したものをclient_userという変数に代入しています。 -
auth_tokens = client_user.create_new_auth_token
について。まずcreate_new_auth_token
とはdevise_token_authのDeviseTokenAuth::Concerns::Userをincludeしていたら使えるパブリックメソッドです。このメソッドは名前の通り、必要なメタデータを全て含んでいる新しいトークンを作成できます。つまり先ほど作成したclient_user
のトークンを作成して、これをauth_tokens
に代入しています。
なぜ認証が通らなかったのか?
ユーザーをDBに保存できていなかったから?
なぜならcreateをbuildにすると認証エラーになってしまうので。
実際にDBに保存されているemaillとpasswordを用いているのに認証に通らなかったのは分からずじまいです。