为什么在测试中设置cookie,而不在控制器中显示? [英] Why does a cookie set in a test, not show up in a controller?

查看:93
本文介绍了为什么在测试中设置cookie,而不在控制器中显示?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这最初是一个我无法通过Rails教程解决的问题,但是在这一点上,我只想了解发生了什么事情,如果可以的话,我应该能够解决我在教程中遇到的问题。 / p>

我的问题归结为这个问题。我试图在测试中设置一个cookie,然后在执行放置操作后在控制器中检查它的值,但我在控制器中看不到该cookie。



下面是测试中的代码:

 描述作为错误的用户 
let(:user){ FactoryGirl.create(:user)}
let(:wrong_user){FactoryGirl.create(:user,email: wrong@example.com)}
之前
会进行设置测试-设置remeber_token
cookies ['remember_token'] = user.remember_token
放入 cookies ['remember_token'] =#{cookies ['remember_token']}
结尾
描述将PUT请求提交给Users#update动作先执行
,然后再执行
进行测试
进行 cookies ['remember_token'] =#{cookies ['remember_token' ]}
放置user_path(wrong_user)
结束
指定{response.should redirect_to(root_url)}
结束
结束

这是控制器中的代码(I t认为这就是所有相关的内容)

  before_filter:signed_in_user,仅:[:edit,:update] 
before_filter :correct_user,仅:[:edit,:update]

defsigned_in_user
放入 insigned_in_user过滤器
放入 cookies ['remember_token'] =#{cookies [' Remember_token']}
redirect_to signin_url,注意:请登录。除非登录?
end

defcorrect_user
@user = User.find(params [:id])
redirect_to(root_url)除非current_user?(@ user)
end

当我运行测试时,输出似乎表明在测试中设置了cookie,但是在之前的过滤器中消失了。该测试最终失败,因为因为 signed_in?方法应该查看用户是否存在,并且该用户的cookie_token是从cookie对象检索到的,为nil。有人可以解释这是怎么回事吗?



这是控制台输出:

 > bundle exec rspec spec / requests / authentication_pages_spec.rb -e向用户#update动作提交PUT请求 
运行选项:include {:full_description => / submitting\ a\ \ PUT\请求\用户\#update\操作/}
设置测试-设置remeber_token
cookie ['remember_token'] = qpcZCCuhaoBirjWR9s5YMw
in测试
cookie ['remember_token'] = qpcZCCuhaoBirjWR9s5YMw
在signed_in_user过滤器中
cookie ['remember_token'] =
F

故障:

1)身份验证授权为错误的用户,向Users#update操作
提交了PUT请求失败/错误:指定{response.should redirect_to(root_url)}
预期响应为重定向到< http://www.example.com/>但重定向到< http://www.example.com/signin>
#./spec/requests/authentication_pages_spec.rb:84:in`top(必需)>中的块(5级)'

在0.34502秒内完成
1个示例,1个失败

失败示例:

rspec ./spec/requests/authentication_pages_spec.rb:84#身份验证授权为错误的用户,向用户提交了PUT请求#

更新操作:
我尝试使用request.cookies ['remember_token' ]在测试中设置Cookie并在before过滤器中检索,而我遇到了同样的问题。



所以基本上我有这个问题:

 描述作为错误的用户 
描述在Users控制器中做
let(:user) {FactoryGirl.create(:user)}
let(:wrong_user){FactoryGirl.create(:user,email: wrong@example.com)}

放置设置之前测试-设置remeber_token
获得root_url
request.cookies ['remember_token'] =用户.remember_token
放置 cookies ['remember_token'] =#{request.cookies ['remember_token']}
结束

描述访问Users#edit页面 b $ b {之前访问{visit edit_user_path(wrong_user)}}
it {should_not have_selector('title',text:full_title('Edit user'))}
end

描述将PUT请求提交给Users#update操作,然后
放入测试中
放入 cookies ['remember_token'] =#{request.cookies ['remember_token'] }
放置user_path(wrong_user)
结束
指定{response.should redirect_to(root_url)}
结束
结束

并在before_filter中:

  defsigned_in_user 
放入 insigned_in_user过滤器
放入 cookies [:remember_token] =#{request.cookies [:remember_token]}
放入 request =#{request.cookies}
p请求
redirect_t o signin_url,注意:请登录。除非登录?
end

和puts request =#{request.cookies}
返回=> request = {}



更新:



我现在了解这里发生了什么。我也已经回顾了本教程,以了解是否错过了某些内容,或者找到了解决此问题的正确方法。
这是正在发生的事情。



在ApplicationController中,我有此文件(直接从教程中复制)

 类ApplicationController< ActionController :: Base 
protect_from_forgery
include SessionsHelper

#强制退出以防止CSRF攻击
def handle_unverified_request
sign_out
super
结束
结束

会话助手具有以下sign_out方法:

  def sign_out 
退出
cookies.delete:remember_token
self.current_user = nil
end

那么发生的是,当我进行测试时,用户会退出结果是重定向到登录页面,而不是root_url。
我必须仔细阅读本教程,以了解可能遗漏的内容,或者是疏忽大意?



已解决!



事实证明这是一个非常简单的设置问题在我的环境中
我已经设置了环境变量RAILS_ENV = development。
删除允许spec_helper.rb中的第一行正确地将RAILS_ENV设置为 test,从而在测试环境中关闭了protect_from_forgery,从而防止了我在放置推杆时的sign_out,并允许测试通过。



我怀疑许多其他人是否会遇到同样的问题,但是如果您正在通过Rails教程并且未通过以下测试,请确保您的测试在测试环境。



失败:

  1)身份验证授权错误用户向Users#update操作
提交PUT请求失败/错误:指定{response.should redirect_to(root_url)}
期望的响应是重定向到< http://www.example .com />但重定向到< http://www.example.com/signin>
#./spec/requests/authentication_pages_spec.rb:84:in`top(必需)>'

解决方案

最终,问题在于测试是在开发环境而不是测试环境中运行的。在开发环境中,protect_from_forgery处于打开状态,在这种情况下,触发了对sign_out的调用,该调用最终删除了cookie。这就是为什么它在控制器中不可用的原因。解决环境变量问题后,现在可以在测试环境中运行测试,并且cookie在控制器中按预期显示。有关更多详细信息,请参见更新的已解决!部分。问题。


This started out as a problem I could not get past in the rails tutorial, but at this point I would just like to understand whats going on, if I can I should be able to get past my problem in the tutorial.

My problem boils down to this. I am trying to set a cookie in a test, and then check it's value in the controller after doing a put, but I don't see the cookie in the controller.

Here is the code in the test:

describe "as wrong user" do
  let(:user) { FactoryGirl.create(:user) }
  let(:wrong_user) { FactoryGirl.create(:user, email: "wrong@example.com") }
  before do
      puts "setting up test - set remeber_token"
      cookies['remember_token'] = user.remember_token
      puts "cookies['remember_token'] = #{cookies['remember_token']}"
  end
  describe "submitting a PUT request to the Users#update action" do
    before do 
      puts "in test " 
      puts "cookies['remember_token'] = #{cookies['remember_token']}"
      put user_path(wrong_user) 
    end
    specify { response.should redirect_to(root_url) }
  end
end

and here is the code in the controller (I think this is all that is relevant)

before_filter :signed_in_user, only: [:edit, :update]
before_filter :correct_user,   only: [:edit, :update]

    def signed_in_user
      puts "in signed_in_user filter"
      puts "cookies['remember_token'] = #{cookies['remember_token']}"
      redirect_to signin_url, notice: "Please sign in." unless signed_in?
    end

    def correct_user
      @user = User.find(params[:id])
      redirect_to(root_url) unless current_user?(@user)
    end

When I run the tests the output seems to indicate that the cookie is set in the test but is gone in the before filter. The test ultimately fails because because the signed_in? method is supposed to see if a user exists with the remember_token retrieved from the cookies object, which is nil. Can someone explain what is going on here?

Here is the console output:

>bundle exec rspec spec/requests/authentication_pages_spec.rb -e "submitting a PUT request to the Users#update action"
Run options: include {:full_description=>/submitting\ a\ PUT\ request\ to\ the\ Users\#update\ action/}
setting up test - set remeber_token
cookies['remember_token'] = qpcZCCuhaoBirjWR9s5YMw
in test
cookies['remember_token'] = qpcZCCuhaoBirjWR9s5YMw
in signed_in_user filter
cookies['remember_token'] =
F

Failures:

  1) Authentication authorization as wrong user submitting a PUT request to the Users#update action
     Failure/Error: specify { response.should redirect_to(root_url) }
       Expected response to be a redirect to <"http://www.example.com/"> but was a redirect to <"http://www.example.com/signin">
     # ./spec/requests/authentication_pages_spec.rb:84:in `block (5 levels) in <top (required)>'

Finished in 0.34502 seconds
1 example, 1 failure

Failed examples:

rspec ./spec/requests/authentication_pages_spec.rb:84 # Authentication authorization as wrong user submitting a PUT request to the Users#update action

UPDATE: I tried using request.cookies['remember_token'] to set the cookie in the test and retrieve in the before filter, and I am having the same issue.

so basically I have this:

describe "as wrong user" do
  describe "in the Users controller" do
    let(:user) { FactoryGirl.create(:user) }
    let(:wrong_user) { FactoryGirl.create(:user, email: "wrong@example.com") }
    before do 
      puts "setting up test - set remeber_token"
      get root_url
      request.cookies['remember_token'] = user.remember_token
      puts "cookies['remember_token'] = #{request.cookies['remember_token']}" 
    end  

    describe "visiting Users#edit page" do
      before { visit edit_user_path(wrong_user) }
      it { should_not have_selector('title', text: full_title('Edit user')) }
    end

    describe "submitting a PUT request to the Users#update action" do
      before do 
        puts "in test " 
        puts "cookies['remember_token'] = #{request.cookies['remember_token']}"
        put user_path(wrong_user) 
      end
      specify { response.should redirect_to(root_url) }
    end
  end

and in the before_filter :

  def signed_in_user
      puts "in signed_in_user filter"
      puts "cookies[:remember_token] = #{request.cookies[:remember_token]}"
      puts "request = #{request.cookies}"
      p request
      redirect_to signin_url, notice: "Please sign in." unless signed_in?
    end

and the puts "request = #{request.cookies}" returns => request = {}

Update:

I now understand what is going on here. I have too look back through the tutorial to see if I missed something, or find the correct way around this. Here is what is happening.

In the ApplicationController I have this (copied directly from the tutorial)

class ApplicationController < ActionController::Base
  protect_from_forgery
  include SessionsHelper

  # Force signout to prevent CSRF attacks
  def handle_unverified_request
    sign_out
    super
  end   
end

The sessions helper has this sign_out method:

  def sign_out
    puts "in sign out"
    cookies.delete :remember_token
    self.current_user = nil
  end

So what happens is that when I do the put in the test, the user gets signed out and as a result is redirected to the sign in page rather than the root_url. I have to look through the tutorial to see what I might have missed, or maybe it's an oversight?

SOLVED!

It turns out this was a very simple set up issue in my environment. I had set the environment variable RAILS_ENV="development". Removing that allows the first line in the spec_helper.rb to correctly set the RAILS_ENV to 'test' which turns protect_from_forgery off in the test env, which prevents the sign_out when I do the put, and allows the test to pass.

I doubt many others will have this same issue, but if you are going through the rails tutorial and are failing the following test, make sure your tests are being run in the test environment.

Failures:

  1) Authentication authorization as wrong user submitting a PUT request to the Users#update action
     Failure/Error: specify { response.should redirect_to(root_url) }
       Expected response to be a redirect to <"http://www.example.com/"> but was a redirect to <"http://www.example.com/signin">
     # ./spec/requests/authentication_pages_spec.rb:84:in `block (5 levels) in <top (required)>'

解决方案

Ultimately the issue was that the tests were being run in the "development" environment rather than the "test" environment. In the development environment, protect_from_forgery is on, which, in this case, triggered a call to sign_out which ultimately deleted the cookie. That's why it is not available in the controller. After fixing an environment variable problem, the tests are now run in the "test" environment, and the cookie shows up as expected in the controller. For more details see the updated section "SOLVED!" in the question.

这篇关于为什么在测试中设置cookie,而不在控制器中显示?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆