【问题标题】:how do i test cookie expiry in rails rspec我如何在rails rspec中测试cookie过期
【发布时间】:2011-06-27 12:11:43
【问题描述】:

在 rspec 中设置 cookie 有很多困惑 http://relishapp.com/rspec/rspec-rails/v/2-6/dir/controller-specs/file/cookies

在你的控制器中,通常你可以写

cookies['transaction_code'] = { :expires => 300.seconds.from_now, :value => c }

但在 rspec 我只能写

request.cookies['transaction_code'] = transaction_code

如果我说

request.cookies['transaction_code'] = { :expires => 300.seconds.from_now, :value => c }

我在控制器中将哈希值作为 cookies['transaction_code'] 的值返回。

现在我的问题是:如何在 rspec 控制器测试示例中设置/测试 cookie 过期时间?

更新:几秒钟后想到:我的意思是:我如何测试控制器是否按预期对过期的 cookie 做出反应,但实际上,如果我信任 cookie 实现,过期的 cookie 就像没有 cookie,我应该做,所以毕竟也许我的问题没有意义。如果是这种情况,我需要测试(另一个)控制器操作是否正确设置了过期 cookie,但是如果测试中的 cookies['transaction_code'] 只返回值,我该怎么做?

【问题讨论】:

    标签: ruby-on-rails-3 cookies rspec


    【解决方案1】:

    浏览器do not send cookie attributes back to the server。这就是为什么您只能将键值对发送到操作。

    由于您可以假设 Rails、Rack 和浏览器使用参数做正确的事情,您真正需要测试的只是您的代码传递给CookieJar 的参数。

    要测试过期设置是否正确在设置 cookie 的控制器中,您可以删除 #cookies 方法并确保将正确的设置传递给它。

    # app/controllers/widget_controller.rb
    ...
    def index
        cookies[:expiring_cookie] = { :value   => 'All that we see or seem...', 
                                      :expires => 1.hour.from_now }
    end
    ...
    
    # spec/controllers/widget_controller_spec.rb
    ...
    it "sets the cookie" do
      get :index
      response.cookies['expiring_cookie'].should eq('All that we see or seem...')
                                                   # is but a dream within a dream.
                                                   #                - Edgar Allan Poe
    end
    
    it "sets the cookie expiration" do
      stub_cookie_jar = HashWithIndifferentAccess.new
      controller.stub(:cookies) { stub_cookie_jar }
    
      get :index
      expiring_cookie = stub_cookie_jar['expiring_cookie']
      expiring_cookie[:expires].to_i.should be_within(1).of(1.hour.from_now.to_i)
    end
    ...
    

    比这更多的测试是沸腾的海洋。在某些时候,您必须假设您所在的堆栈(例如,Rails、Rack、Web 服务器、TCP/IP、操作系统、Web 浏览器等)正常工作并专注于您控制的代码。

    【讨论】:

    • 不错的一个 kro,我接受你的回答,我不确定存根 cookiestore,提到对 cookie 罐的明显访问与使用符号或字符串作为键无关,这与哈希存根不同。总的来说,我对框架的一部分感到不安。另外,类似 expiring_cookie[:expires].to_i.should be_within(1).of(1.hour.from_now.to_i) 是测试动态时间设置的最佳实践吗?
    • 不,我可能会在实际规范中对 DateTime 的匹配器做一些不同的事情。我的目标是提供一些可以作为插图通过的东西,因为 == 不会。
    • 至于你无所谓的访问问题;这很容易通过使用ActiveSupport::HashWithIndifferentAccess 而不是标准库Hash 来解决。我更新了示例代码以反映这一点。
    【解决方案2】:

    我带着这个来自未来:

      it 'sets the cookie expiration' do
        stub_cookie_jar = HashWithIndifferentAccess.new
        allow(controller).to receive(:cookies).and_return(stub_cookie_jar)
        get :index
        expiracy_date = stub_cookie_jar[:expires]
        expect(expiracy_date).to be_between(1.hour.from_now - 1.minutes, 
                                            1.hour.from_now)
      end
    

    【讨论】:

    • 我遇到了 RSpec 的内置 cookie 支持问题,切换到这个,一切正常!
    【解决方案3】:

    另一个使用Timecop的选项:

    Timecop.freeze(Time.now)
    
    expect(controller.send(:cookies)).to receive(:[]=).with('cookie_name',
      value:   'whatever',
      expires: 1.hour.from_now
    )
    
    get :index
    

    【讨论】:

      【解决方案4】:

      在您的规范中将 request.cookies['transaction_code'] 设置为 CGI::Cookie。 http://www.ruby-doc.org/stdlib/libdoc/cgi/rdoc/classes/CGI/Cookie.html#M000169

      【讨论】:

      • 即使您将CGI::Cookie 对象传递给request.cookies(在调用操作之前),response.cookies 哈希仍然只返回一个String
      【解决方案5】:

      如果您想同时检查多个 cookie 属性,请检查 Set-Cookie 标头,如下所示:

      it 'expires cookie in 15 minutes' do
        travel_to(Date.new(2016, 10, 25))
        post 'favorites', params: { flavor: 'chocolate' }
        travel_back
      
        details = 'favorite=chocolate; path=/; expires=Tue, 25 Oct 2016 07:15:00 GMT; HttpOnly'
        expect(response.header['Set-Cookie']).to eq details
      end
      

      这有点脆弱,因为 cookie 的其他非关键属性可能会破坏此字符串。但它确实让您远离 Rails 内部,并允许您一次检查多个属性。

      更好的方法是一次只匹配一个属性,这是一种更健壮的方法,不会那么容易受到 Set-Cookie 字符串的构造方式或您可能添加到 cookie 的其他属性的影响未来:

        expect(response.header['Set-Cookie']).to match(
          /favorite=chocolate.*; expires=Tue, 25 Oct 2016 07:15:00 GMT/
        )
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-07-06
        • 1970-01-01
        • 1970-01-01
        • 2012-06-15
        • 1970-01-01
        相关资源
        最近更新 更多