在Rails 5控制器集成测试中设置cookie.signed

Yi *_*eng 8 cookies unit-testing ruby-on-rails ruby-on-rails-5

想象一下,有一个控制器集成测试调用控制器方法的场景,其中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
Run Code Online (Sandbox Code Playgroud)

控制器测试

# 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
Run Code Online (Sandbox Code Playgroud)

但是,我不确定如何cookie.signed在测试中进行设置.上面的测试代码抛出一个异常:

NoMethodError:未定义的方法`签名'为Rack :: Test :: CookieJar:0x007fe90965ccd8

试图找到一个解决方案,但我能找到的最接近的是这篇文章,https://sikac.hu/reconstruct-a-cookie-jar-and-read-signed-cookie-in-capybara-f71df387f9ff,但却无法找到弄清楚如何构建ActionDispatch::Request对象.

Bor*_*aMa 15

这似乎是Rails 5及更高版本中的一个已知错误(链接问题大约cookies.encrypted但同样适用cookies.signed).问题是在控制器测试中,cookie jar是一个不支持签名/加密cookieRack::Test::CookieJar类实例.另一方面,在应用程序本身中,cookie jar是一个类实例,它支持这两种特殊的cookie类型.ActionDispatch::Cookies::CookieJar

不过,要在控制器测试中构建一个已签名的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
Run Code Online (Sandbox Code Playgroud)

第一个测试行创建一个新ActionDispatch请求,应用程序请求默认环境设置(它们定义例如用于签名cookie的秘密)并返回它的cookie jar.然后,您只需将:token签名的cookie 设置为所需的值(此cookie jar 确实具有signed定义的方法,因为这ActionDispatch::Cookies::CookieJar不是Rack::Test::CookieJar).最后,您检索签署cookie的值通过访问没有signed访问,并设置同名检测Cookie,使用此值.

现在,当测试到达控制器代码时,控制器应该在cookies.signed[:token]cookie中看到正确的值.

  • 像这样的解决方案正是我所寻找的,但我一生都无法让它发挥作用。无论我做什么,在请求期间都无法解析会话cookie。 (2认同)