LoginSignup
3
4

More than 3 years have passed since last update.

devise_token_auth ログアウトのテストコード実装時に苦戦したことをまとめる

Posted at

devise_token_auth でログアウトのテストコード作成時、エラー解決の情報が少なかったのでまとめます。
※ user の新規登録、ログイン、ログアウト機能を実装しているものとします。
※ FactoryBot を導入してます。

headers にログインに必要な情報が入っていないため、エラー発生

エラー発生時のコード

describe "DELETE /v1/auth/user/sign_out" do
  subject { delete(destroy_v1_user_session_path) }
  context "トレーナーログアウト時" do
    let(:user) { create(:user) }
    it "トークンを無くし、ログアウトできる" do
      subject
      expect(response).to have_http_status(200)
    end
  end
end

エラー内容

Failure/Error: expect(response).to have_http_status(200)
expected the response to have status code 200 but it was 404

正常なレスポンス(200)ではなく、リクエストが存在しない(404)エラーが出てます。との内容。
subject の下に binding.pry を入れ、デバック画面にしuser を実行

#<Trainer id: 532, provider: "email", uid: "6_hannah@emmerich.name", allow_password_change: false, name: "松本 七海", nickname: nil, email: "6_hannah@emmerich.name", address: nil, birthday: nil, created_at: "2020-07-26 06:10:35", updated_at: "2020-07-26 06:10:35">

user の中にデータがあることを確認できました。
次に headers 情報を確認するため、response.headers を実行。

{"X-Frame-Options"=>"SAMEORIGIN",
 "X-XSS-Protection"=>"1; mode=block",
 "X-Content-Type-Options"=>"nosniff",
 "X-Download-Options"=>"noopen",
 "X-Permitted-Cross-Domain-Policies"=>"none",
 "Referrer-Policy"=>"strict-origin-when-cross-origin",
 "Content-Type"=>"application/json; charset=utf-8",
 "Cache-Control"=>"no-cache",
 "X-Request-Id"=>"a2ad39e6-d2b2-4ae8-93c1-5ddcd2ea22d1",
 "X-Runtime"=>"0.010570",
 "Content-Length"=>"71"}

headers の情報は返ってきましたが、ログアウトに必要な情報
access-tokenclientuid が入ってないことが分かります。
headers にログアウトに必要な情報が入ってないから、404の異常系のエラーが発生している。
新規作成時、ログイン時にトークン情報が発行され、その情報をもとにログアウトの処理を行うのですが、現状のコードでは user の情報は作成されても、トークン情報は作成されていない状況です。
なので、トークン情報を入れてあげましょう。

describe "DELETE /v1/auth/user/sign_out" do
  subject { delete(destroy_v1_user_session_path, headers: headers) }
  context "トレーナーログアウト時" do
    let(:user) { create(:user) }
    let(:headers) { user.create_new_auth_token }
    it "トークンを無くし、ログアウトできる" do
      subject
      expect(response).to have_http_status(200)
    end
  end
end

create_new_auth_tokenメソッドで、必要なメタデータ全てを含む新しい認証トークンを作成します。
subject の下に binding.pry を入れheadersを実行し、データが入っていればオッケーです。

ログアウト時にトークン情報が残ったままのため、エラー発生

ログアウトは、「有効なトークン情報がなくなる」なので、先ほどのコードにトークン情報の有無を確認するテストコードを追記しました。

describe "DELETE /v1/auth/user/sign_out" do
    subject { delete(destroy_v1_user_session_path, headers: headers) }
    context "トレーナーログアウト時" do
      let(:user) { create(:user) }
      let(:headers) { user.create_new_auth_token }
      it "トークンを無くし、ログアウトできる" do
        subject
+       expect(user.tokens).to be_blank
        expect(response).to have_http_status(200)
      end
    end
  end

エラー内容

Failure/Error: expect(trainer.tokens).to be_blank
expected `{"LT4SdlN2czyzNnwTfLGjTw"=>{"expiry"=>1596957557, "token"=>"$2a$10$BgZ4YItos1hQRTp4y1JvZ.mIsreaIxD1NC3ckRk0euxsk8IBkoM7K", "updated_at"=>"2020-07-26 07:19:17 UTC"}}.blank?` to return true, got false

トークン情報が残ったままとのエラーです。
ログアウトに必要な情報を user に入れ、ログアウトの処理はできても、user の値は更新されないので残ったままになっています。
user の値を更新するためには、user.reload.tokenと記述してあげる必要があります。

describe "DELETE /v1/auth/user/sign_out" do
    subject { delete(destroy_v1_user_session_path, headers: headers) }
    context "トレーナーログアウト時" do
      let(:user) { create(:user) }
      let(:headers) { user.create_new_auth_token }
      it "トークンを無くし、ログアウトできる" do
        subject
        expect(user.reload.tokens).to be_blank
        expect(response).to have_http_status(200)
      end
    end
  end

以上の内容にすれば、ログアウト後の user の値が更新されるため、user にトークン情報がなくなります。

3
4
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
3
4