【问题标题】:Why does a cookie set in a test, not show up in a controller?为什么在测试中设置的 cookie 不显示在控制器中?
【发布时间】:2014-02-08 05:03:21
【问题描述】:

这开始是一个问题,我无法在 rails 教程中解决问题,但此时我只想了解发生了什么,如果可以的话,我应该能够解决教程中的问题。

我的问题归结为这个。我正在尝试在测试中设置一个 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? 方法应该查看用户是否存在,并且从 cookie 对象检索到的 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}" 返回 => 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)>'

【问题讨论】:

    标签: ruby-on-rails cookies


    【解决方案1】:

    尝试改变cookies['remember_token'] = user.remember_token 到您的before 块中的request.cookies['remember_token'] = user.remember_token

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

    【讨论】:

    • 我实际上也曾尝试过这一点。我使用 request.cookies[] 时遇到的问题是我得到“nil:NilClass 的未定义方法'cookies'”。我错过了什么要求吗?
    • 您应该描述控制器。但在您的示例中,您似乎描述了 Authentication 类。
    • 我的设置与教程中的设置相同,但我确实尝试使用 describe UsersController 块并得到相​​同的结果。有人知道为什么请求会为零吗?
    • 我设法通过先获取 root_url 来获得一个非零请求对象,所以现在我可以使用 request.cookies,但我仍然遇到同样的问题...... request.cookies 是before_filter 中的空白
    【解决方案2】:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-02-27
      • 1970-01-01
      • 2019-12-28
      • 2014-10-14
      • 2017-06-12
      • 1970-01-01
      • 2022-09-23
      • 1970-01-01
      相关资源
      最近更新 更多