如何在Rails 3中测试cookies.permanent.signed
我在某个控制器中有一个动作,它在永久签名的cookie中设置了一些值,如下所示:
def some_action cookies.permanent.signed[:cookie_name] = "somevalue" end
在一些function测试中,我正在尝试测试cookie是否设置正确起诉:
test "test cookies" do assert_equal "somevalue", cookies.permanent.signed[:cookie_name] end
test "test cookies" do assert_equal "somevalue", cookies.permanent.signed[:cookie_name] end
但是,当我运行测试时,我收到以下错误:
NoMethodError: undefined method `permanent' for #
NoMethodError: undefined method `permanent' for #
如果我只尝试:
test "test cookies" do assert_equal "somevalue", cookies.signed[:cookie_name] end
test "test cookies" do assert_equal "somevalue", cookies.signed[:cookie_name] end
我明白了:
NoMethodError: undefined method `signed' for #
NoMethodError: undefined method `signed' for #
如何在Rails 3中测试签名的cookie?
我在谷歌搜索类似问题的解决方案时遇到了这个问题,所以我将在这里发布。 我希望在测试控制器动作之前在Rspec中设置一个已签名的cookie。 以下工作:
jar = ActionDispatch::Cookies::CookieJar.build(@request) jar.signed[:some_key] = "some value" @request.cookies['some_key'] = jar[:some_key] get :show ...
请注意以下内容不起作用:
# didn't work; the controller didn't see the signed cookie @request.cookie_jar.signed[:some_key] = "some value" get :show ...
在rails 3的ActionControlller :: 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
请注意,我们需要设置signed cookie jar.signed[:foo]
,但是读取unsigned cookie jar[:foo]
。 只有这样我们才能获得在assert_equal
进行比较所需的cookie的加密值。
在查看处理此问题的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)
可能有点hackish,但它为我做的工作。
问题(至少在表面上)是在function测试(ActionController :: TestCase)的上下文中,“cookies”对象是哈希,而当你使用控制器时,它是一个ActionDispatch :: Cookies :: CookieJar对象。 所以我们需要将它转换为CookieJar对象,以便我们可以使用“signed”方法将其转换为SignedCookieJar。
您可以将以下内容放入function测试中(在获取请求之后)将Cookie从Hash转换为CookieJar对象
@request.cookies.merge!(cookies) cookies = ActionDispatch::Cookies::CookieJar.build(@request)
问题似乎也是你的测试。
下面是一些代码和测试,我用TDD来设置cookie的值,将params值传递给视图。
function测试:
test "reference get set in cookie when visiting the site" do get :index, {:reference => "121212"} refute_nil cookies["reference"] end
SomeController:
before_filter :get_reference_code
ApplicationController中:
def get_reference_code cookies.signed[:reference] ||= params[:reference] end
请注意,refute_nil行,cookie是一个字符串……这也是使得这个测试没有通过的一件事,就是在cookies[:reference]
一个符号cookies[:reference]
测试不喜欢那样,所以我没有这样做。