#はじめに
モデルのテストを書いているときに、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を返すというわけではないのですね。
マッチャについて勉強してスマートなテストが書けるようになりたいです。
!!による論理値への変換についてはとても汎用性が高そうなので、今後も意識していきます。