为什么cookie在测试中设置,而不是在控制器中显示?

时间:2014-01-18 21:25:14

标签: ruby-on-rails cookies

这开始是我在rails教程中无法解决的问题,但此时我想了解最新情况,如果可以,我应该能够在教程中解决我的问题。< / p>

我的问题归结为此。我试图在测试中设置一个cookie,然后在执行put之后在控制器中检查它的值,但是我没有在控制器中看到cookie。

以下是测试中的代码:

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

这里是控制器中的代码(我认为这是相关的)

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

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

这是控制台输出:

>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

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

基本上我有这个:

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

并在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

和puts“request =#{request.cookies}” returns =&gt; request = {}

更新

我现在明白这里发生了什么。我也回顾了整个教程,看看我是否错过了什么,或者找到了正确的方法。 这是正在发生的事情。

在ApplicationController中我有这个(直接从教程中复制)

class ApplicationController < ActionController::Base
  protect_from_forgery
  include SessionsHelper

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

会话助手有这个sign_out方法:

  def sign_out
    puts "in 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,这会在我执行put时阻止sign_out,并允许测试通过。

我怀疑其他人会遇到同样的问题,但是如果您正在浏览rails教程并且未通过以下测试,请确保您的测试在测试环境中运行。

故障:

  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)>'

2 个答案:

答案 0 :(得分:2)

尝试更改cookies['remember_token'] = user.remember_tokenrequest.cookies['remember_token'] = user.remember_token区块的before

顺便说一下,post对测试中使用cookie有很好的解释。

答案 1 :(得分:0)

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