こんにちは、ペーパーエンジニアのよしこです。
Ruby on Railsのテストで、Cookies周りのバグに対応しました。
RSpecテスト環境での日本語情報が少なかったので、私と同じ初心者向けに情報共有します。
バグの内容
ControllerやHelperなどで使われているcookies.signed[:foo]
をテストで呼び出すと、
NoMethodError: undefined method `signed' for #<Rack::Test::CookieJar:0x0>とエラーになりました。
※ cokkies.permanent
や cookies.encrypted
でも同様のエラーになります。
class hogesController < ApplicationController
def hogehoge
pp cookies.signed[:foo] = "bar"
end
end
上のコントローラー(もしくはヘルパー)のRSpecテストを書きます。
RSpec.describe "Hoges", type: :request do
it { expect(hogehoge).to eq "bar" }
end
実行結果は、エラーとなります。
#ターミナル
$ rspec
Failures:
1) Hoges #hogehoge
Failure/Error: pp cookies.signed[:foo] = "bar"
NoMethodError:
undefined method `signed' for #<Rack::Test::CookieJar:0x00007ffddefd5460>
# ./app/helpers/hoges_controller.rb:3:in
対処方法(結論)
Rack::Test::CookieJarの未定義メソッド (undefined method) を定義し直します。
./spec/support/cookies.rb
というファイル(名前は任意)を作成し、下のコードで保存します。
# RSpecでcookies.signedがエラーになる対処
class Rack::Test::CookieJar
def signed
self
end
def permanent
self
end
def encrypted
self
end
end
これで、 テストはパスできるはずです。
この解決方法は、GitHubのRSpec Issuesのコメントに記載されていました。
【GitHub】Signed cookies not available in controller specs - rspec-rails 3.5.0, rails 5.0 #1658
こちらの最下部コメントがヒントになりました。
@wangthony wangthony commented on 10 Nov 2018
@ivko999 's solution worked for me - thanks!
Even cleaner, just put it in a spec/support file:
# spec/support/cookies.rb class ActionDispatch::Cookies::CookieJar def encrypted; self; end def signed; self; end def permanent; self; end # I needed this, too end
なぜ動かないのか
Railsのcookieクラスは、環境によって参照元が変わります。
# テスト環境以外
ActionDispatch::Cookies::CookieJar
# テスト環境
Rack::Test::CookieJar
テスト環境のRack::Test::CookieJarが、
signed
permanent
encrypted
メソッドをサポートしていないので、
テスト実行時にエラーになってしまいます。
※ ActionController::TestCaseではサポートしているとのことなので、Controllerテストではサポートしているのかもしれません。
【GitHub】Signed cookies not available in controller tests #27145
参考にしたブログ記事
Railsのインテグレーションテストでcookies.signedを使いたい
以上となります。
少しでもお力になれれば幸いです。