Failure/Error: sign_in user
いきなり本題ですが
RailsでDeviseが絡んだrequest specを書いた時に
# 卒制から一部抜粋
Failures:
1) SleepRecords POST /sleep_records 起床記録が作成できる
Failure/Error: sign_in user
NoMethodError:
undefined method `sign_in' for #<RSpec::ExampleGroups::SleepRecords::POSTSleepRecords:0x0000ffff7001db30>
# ./spec/requests/sleep_records_spec.rb:7:in `block (2 levels) in <main>'
このような表示が出て「ん?、request specでsign_inが使えない…?」となりました
はい、request specではsign_inが標準で使えないんだそうです。
最初は AIに聞いたり...Wardenを使ったり...面倒な設定を書いたりしていました。(反省)
...でも大丈夫です!
Devise::Test::IntegrationHelpers
を使用すれば、Wardenを使わずに簡単にログイン状態を作れるようになります。
ここにしっかり書いてありました、公式ドキュメントの大切さを実感しますね。
request spec で sign_in を使えるようにする設定
rails_helper.rb に以下を追加します:
RSpec.configure do |config|
# request spec でも sign_in/sign_out が使えるようになる
config.include Devise::Test::IntegrationHelpers, type: :request
end
これだけで OK
Wardenを使った面倒な設定やWarden.test_reset!
は不要です。
使い方(例)
RSpec.describe "SleepRecords", type: :request do
let(:user) { FactoryBot.create(:user) }
before do
sign_in user
end
it "起床記録が作成できる" do
post sleep_records_path, params: { sleep_record: { slept_at: Time.current } }
expect(response).to have_http_status(:redirect)
follow_redirect!
expect(response.body).to include("Sleep record was successfully created")
end
end
POINT!
- sign_in user でログイン状態を簡単に作れる
- sign_out user でログアウト状態に戻せる
- controller specとほぼ同じ書き方でrequest specが書ける
↑Warden概要
複雑なことが書いてありすぎて理解不十分ではありますが
Warden はさらに厳密に認証処理を確認したいときに使うものという認識で良さそう
(補足)sign_in と login_as(Warden) の違い
項目 | sign_in(IntegrationHelpers) | login_as(Warden) |
---|---|---|
提供元 | Devise | Warden |
動作レイヤー | Integration / request spec | Rack |
認証フロー | 擬似的(セッションに直接ログイン) | 本物の Warden 認証を通す |
設定の手軽さ | ○ | △(Warden.test_reset! 等が必要) |
本番に近いか | △ | ○ |
Rackとは:RubyでWebアプリケーションとWebサーバーをつなぐための共通インターフェース
結論:普通のrequest specなら、sign_inで十分
- request specで Devise のログイン状態を作るのに Warden は必須でない
- Devise::Test::IntegrationHelpers を使うと簡潔で分かりやすい