18

我在一些控制器中有一个操作,它在永久签名的 cookie 中设置了一些值,如下所示:


def some_action
    cookies.permanent.signed[:cookie_name] = "somevalue"
end

在一些功能测试中,我正在尝试测试 cookie 是否设置正确,并以此起诉:


test "test cookies" do
    assert_equal "somevalue", cookies.permanent.signed[:cookie_name]
end


但是,当我运行测试时,出现以下错误:


NoMethodError: undefined method `permanent' for #

如果我只尝试:


test "test cookies" do
    assert_equal "somevalue", cookies.signed[:cookie_name]
end


我得到:


NoMethodError: undefined method `signed' for #

如何在 Rails 3 中测试签名的 cookie?

4

5 回答 5

18

I came across this question while Googling for a solution to a similar issue, so I'll post here. I was hoping to set a signed cookie in Rspec before testing a controller action. The following worked:

jar = ActionDispatch::Cookies::CookieJar.build(@request)
jar.signed[:some_key] = "some value"
@request.cookies['some_key'] = jar[:some_key]
get :show ...

Note that the following didn't work:

# didn't work; the controller didn't see the signed cookie
@request.cookie_jar.signed[:some_key] = "some value"
get :show ...
于 2011-07-18T03:59:24.640 回答
8

在 rails 3 的 ActionController::TestCase 中,您可以像这样在请求对象中设置签名的永久 cookie -

 @request.cookies.permanent.signed[:foo] = "bar"

并且可以通过执行此操作来测试从控制器中执行的操作返回的签名 cookie

 test "do something" do
     get :index # or whatever
     jar = @request.cookie_jar
     jar.signed[:foo] = "bar"
     assert_equal jar[:foo], @response.cookies['foo'] #should both be some enc of 'bar'
 end 

请注意,我们需要设置已签名的 cookie jar.signed[:foo],但要读取未签名的 cookie jar[:foo]。只有这样我们才能得到 cookie 的加密值,在assert_equal.

于 2011-03-30T06:08:12.453 回答
7

在查看了处理此问题的 Rails 代码后,我为此创建了一个测试助手:

  def cookies_signed(name, opts={})
    verifier = ActiveSupport::MessageVerifier.new(request.env["action_dispatch.secret_token".freeze])
    if opts[:value]
      @request.cookies[name] = verifier.generate(opts[:value])
    else
      verifier.verify(cookies[name])
    end
  end

将此添加到 test_help.rb,然后您可以使用以下命令设置签名 cookie:

cookies_signed(:foo, :value => 'bar')

并阅读:

cookies_signed(:foo)

也许有点骇人听闻,但它对我有用。

于 2012-02-01T10:24:39.883 回答
2

问题(至少在表面上)是在功能测试(ActionController::TestCase)的上下文中,“cookies”对象是一个哈希,而当您使用控制器时,它是一个 ActionDispatch::Cookies:: CookieJar 对象。所以我们需要将其转换为 CookieJar 对象,以便我们可以使用其上的“签名”方法将其转换为 SignedCookieJar。

您可以将以下内容放入功能测试中(在获取请求之后),以将 Cookie 从 Hash 转换为 CookieJar 对象

@request.cookies.merge!(cookies)
cookies = ActionDispatch::Cookies::CookieJar.build(@request)
于 2011-03-02T22:09:53.680 回答
0

问题似乎还在于您的测试。

下面是一些代码和测试,我用于 TDD 您希望通过将参数值传递到视图中来设置 cookie 值的情况。

功能测试:

test "reference get set in cookie when visiting the site" do
  get :index, {:reference => "121212"}
  refute_nil cookies["reference"]
end

一些控制器:

before_filter :get_reference_code

应用控制器:

def get_reference_code
  cookies.signed[:reference] ||= params[:reference]
end

请注意, refute_nil 行,cookie 是一个字符串......这也是使该测试无法通过的一件事,在测试中放置了一个符号cookies[:reference]不喜欢那样,所以我没有这样做。

于 2011-08-06T11:48:33.773 回答