Help us understand the problem. What is going on with this article?

【Rails】authenticateメソッドが返すもの

はじめに

モデルのテストを書いているときに、authenticateメソッドの検証で少しつまづきました。
簡単な内容ですがエラーの理由・対策を記載します。

authenticateメソッド

has_secure_passwordメソッドをユーザーモデルで呼び出すだけで使えるようになるメソッド。
パスワードを引数としてユーザーの認証を行うことができる。

ユーザーモデルのテスト(RSpec)

まずは誤ったパスワードを入力した場合のテスト。
(FactoryBotではパスワードを"password"と設定)

(略)
context '正しくないパスワードの場合' do
      it '認証がされない' do
        expect(user.authenticate("invalid_password")).to eq(false)
      end
    end
(略)

問題なく通過。

次に、正しいパスワードを入力した場合のテスト。

(略)
context '正しいパスワードの場合' do
      it '正常に認証される' do
        expect(user.authenticate("password")).to eq(true)
      end
    end
(略)

これではテストが通らず、ログの中身はこんな感じ。

expected: true
got: #<User id: *, name: "テストユーザーn", created_at: "2020-02-29 02:11:51", updated_at: "2020-02-29 02:11:5...stn@example.com",  password_digest: [FILTERED]>

「true」を期待していたところ、実際にはユーザーオブジェクトが返ってきた。

つまり、authenticateメソッドは、
・誤ったパスワードの場合 → falseを返す
・正しいパスワードの場合 → そのユーザーを返す
ということ。

テストが通るようにするには、!!によってユーザーオブジェクトを論理値オブジェクトに変換してあげる必要がある。

(略)
context '正しいパスワードの場合' do
      it '正常に認証される' do
        expect(!!user.authenticate("password")).to eq(true)
      end
    end
(略)

追記(2020年2月29日)

@asm様よりご指摘をいただきました。ありがとうございます。
be_truthyマッチャを使用すればテストが通ります。

(略)
context '正しいパスワードの場合' do
      it '正常に認証される' do
        expect(user.authenticate("password")).to be_truthy
      end
    end
(略)

これでテスト通過。

まとめ

誤ったパスワードの場合falseを返すからといって、
正しいパスワードの場合trueを返すというわけではないのですね。

マッチャについて勉強してスマートなテストが書けるようになりたいです。

!!による論理値への変換についてはとても汎用性が高そうなので、今後も意識していきます。

hakusai_it
日々勉強
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away