devise_token_auth使用時のRspecの認証処理のやり方

## 概要
Railsで`devise_token_auth`を使用して認証機構を実装しております。
Rspecを利用してテストを書いている際に、テスト内でトークン認証をさせるのに手間取ったので
備忘録としてアウトプットしたいと思います。

## 方法
ここでは、`devise_token_auth`を使用してトークン認証をしている場合と、
`devise`を使用してトークンを使わない認証の場合に分けて記載します。
使用例としてはログインしたユーザーが投稿を作成するというテストを考えていきます。
__なおここからは認証のやり方を示すことに重点を置いているためすべて簡易的にコードを記載していきます。__

#### deviseを使用した場合
通常`devise`を使用した場合は`sign_in`というヘルパーメソッドを使用してテスト内でログイン認証を行います。
まず、下記の投稿に関するcontrollerがあるとします。
またコード中に出てくる`authenticated_user!`、`current_user`、`sign_in`などはdeviseを導入すると
使用できるヘルパーメソッドです。
使用方法を詳しく確認したい場合は下記をご確認ください。
[devise github](https://github.com/heartcombo/devise)

_*controllers/posts_controller.rb*_

```ruby
class PostsController < ApplicationController
  before_action :authenticated_user!, only: [:create]

  def create
    # userモデルとpostモデル間での関連付けはされていると仮定
    current_user.posts.create(params[:post]) #本来はストロングパラメーターを使用してrequestのパラメーターを制限すべきです
  end
end
```

_*spec/requests/posts_spec.rb*_

```ruby
#省略
describe 'POST /create' do
  let!(:user) { { name: 'example_user', email: 'example@example.com', password: 'passward' } }
  let(:post_params) { { content: 'example_content' } }

  before do
    sign_in user
    post posts_path, params: { post: post_params }
  end

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

##### ＜備考＞
下記のように__rails_helper.rb__にてヘルパーをincludeするとrequest spec内で`sign_in`などのヘルパーが使用できます。

spec/rails_helper.rb

```ruby
RSpec.configure do |config|
# 省略
  config.include Devise::Test::IntegrationHelpers, type: :request
end
```

以上でdeviseを使ったログイン認証をする事ができます。

#### devise_token_authを使用してトークン認証している場合
devise_token_authの基本使用の仕方はdeviseとほぼ同じです。
しかしトークン認証を行っているので、deviseを使用したときのようにただヘルパーメソッドの`sign_in`を使って
ユーザーをログインさせるだけでは認証ができません。
deviseの場合と同じようにしようとすると、認証エラーで401が返ってきます。

_*controllers/posts_contorller.rb*_

```ruby
class PostsController < ApplicationController
  before_action :authenticated_user!, only: [:create]

  def create
    # userモデルとpostモデル間での関連付けはされていると仮定
    current_user.posts.create(params[:post]) # 本来はストロングパラメーターを使用してrequestのパラメーターを制限すべき
  end
end
```

deviseのヘルパーメソッド`sign_in`ではトークン認証できないので新たにヘルパーメソッドを作成します。

_*spec/support/authorization_spec.rb*_

```ruby
module AuthorizationHelper
  def sign_in(user)
    post posts_path, params: { email: user.email, password: user.password }
    # レスポンスのHeadersからトークン認証に必要な要素を抜き出して返す処理
    response.headers.slice('client', 'uid', 'token-type', 'access-token')
  end
end
```

_*rails_helper.rb*_

```ruby
RSpec.configure do |config|
# 省略
  config.include AuthorizationHelper, type: :request
end
```

_*spec/requests/posts_spec.rb*_

```ruby
#省略
describe 'POST /create' do
  let!(:user) { { name: 'example_user', email: 'example@example.com', password: 'password' } }
  let(:post_params) { { content: 'example_content' } }
　　　　let(:token) { sign_in user } # 追加

  before do
    #sign_in user # 削除
    post posts_path, params: { post: post_params }, headers: token # 追加
  end
 
  it 'ステータスコード200が返ってくる' do
    expect(response.status).to eq 200
  end
end
```

##### ＜備考＞
ヘルパーメソッドを定義する場合はspec配下に__support__ディレクトリを作成しその中にファイルを記載します。
そしてrspecがそのファイルを読み込むように__rails_helper.rb__で設定を行います。

_*rails_helper.rb*_

```ruby
RSpec.configure do |config|
# 省略
  # デフォルトではコメントアウトされています
  Dir[Rails.root.join('spec', 'support', '**', '*.rb')].sort.each { |f| require f }
end
```

以上がdevise_token_authを使用していた場合のrspecにおける認証です。

## 参考文献
[【Rspec・devise token auth】Rails APIアプリのRspecテストでユーザログイン・認証を実装する方法](https://qiita.com/mtoyopet/items/ed1bd4b9c1544d401880)