想象一下,控制器集成测试会调用控制器方法,其中cookie.signed
用于某些完整性检查。
# app/controllers/foo_controller.rb
def index
entity = FooEntity.find_by_id(params[:id])
if entity.nil?
raise ActionController::BadRequest, 'Could not find requested entity.'
else
@is_authorized = entity.token == cookies.signed[:token]
if @is_authorized
# Success! The path to be tested.
else
raise ActionController::BadRequest, 'Unauthorized cookie token.'
end
end
end
# app/test/controllers/foo_test.rb
require 'test_helper'
class FooControllerTest < ActionDispatch::IntegrationTest
test 'should be working' do
cookies.signed[:token] = '7e5201169ef160e31058d2a1976a5552'
get '/foobar/123'
end
end
但是,我不确定如何在测试中设置cookie.signed
。上面的测试代码引发了一个异常:
NoMethodError:未定义方法`签名'为Rack :: Test :: CookieJar:0x007fe90965ccd8
尝试搜索解决方案,但我能找到的最接近的是本文https://sikac.hu/reconstruct-a-cookie-jar-and-read-signed-cookie-in-capybara-f71df387f9ff,但无法弄清楚如何构建ActionDispatch::Request
对象。
答案 0 :(得分:11)
这似乎是Rails 5 及以上的 known bug(链接问题约为cookies.encrypted
,但同样适用于cookies.signed
)。问题是在控制器测试中,cookie jar是Rack::Test::CookieJar
类实例,不支持签名/加密cookie 。另一方面,在应用程序本身中,cookie jar是一个ActionDispatch::Cookies::CookieJar
类实例,它支持这两种特殊的cookie类型。
然而,要在控制器测试中构建一个已签名的cookie,您可以手动创建一个ActionDispatch
请求cookie jar并使用来检索已签名的cookie值:
# app/test/controllers/foo_test.rb
require 'test_helper'
class FooControllerTest < ActionDispatch::IntegrationTest
test 'should be working' do
my_cookies = ActionDispatch::Request.new(Rails.application.env_config.deep_dup).cookie_jar
my_cookies.signed[:token] = '7e5201169ef160e31058d2a1976a5552'
cookies[:token] = my_cookies[:token]
get '/foobar/123'
end
end
第一个测试行创建一个新的ActionDispatch
请求,应用程序请求默认环境设置(它们定义例如用于签名cookie的秘密)并返回它的cookie jar。然后,您只需将:token
已签名的Cookie设置为所需的值(此Cookie jar 已定义signed
方法,因为这是ActionDispatch::Cookies::CookieJar
,而不是{{ 1}})。最后,您检索已签名的Cookie值,方法是在不使用 Rack::Test::CookieJar
访问者的情况下访问,并使用此设置相同名称的测试Cookie 值。
现在,当测试到达控制器代码时,控制器应该在signed
cookie中看到正确的值。