代码之家  ›  专栏  ›  技术社区  ›  0100110010101

如何测试rails ETag缓存?

  •  8
  • 0100110010101  · 技术社区  · 16 年前

    有没有可能覆盖我的控制器,这是高度依赖于etag与单元测试?

    我想做的是:

    当我尝试测试所有的请求(rspec)时,不管我有多少个类似的请求,我仍然会收到200ok而不是304,并且我的头不会被修改。此外,如果我跟踪request.fresh?(response),它总是错误的。

    我已经试过声明ActionController::Base.perform\u caching=true,它不会改变整体情况。

    非常感谢。

    5 回复  |  直到 16 年前
        1
  •  10
  •   szeryf    13 年前

    下面是如何测试第二个请求是否返回304响应:

        get action, params
        assert_response 200, @response.body
        etag = @response.headers["ETag"]
        @request.env["HTTP_IF_NONE_MATCH"] = etag
        get action, params
        assert_response 304, @response.body
    
        2
  •  5
  •   grosser    14 年前

    Rails散列您提供的:etag:

    headers['ETag'] = %("#{Digest::MD5.hexdigest(ActiveSupport::Cache.expand_cache_key(etag))}")
    

    frash_when(:etag => 'foo')
    

    只会由正确的摘要触发(双引号是必需的)

    def with_etag
      if stale?(:etag => 'foo')
        render :text => 'OK'
      end
    end
    
    ... tested by ...
    
    @request.env['HTTP_IF_NONE_MATCH'] = '"acbd18db4cc2f85cedef654fccc4a4d8"'
    get :with_etag
    assert_equal 304, @response.status.to_i
    

    修改后相同:

    def with_modified
      if stale?(:last_modified => 1.minute.ago)
        render :text => 'OK'
      end
    end
    
    ... tested by ...
    
    @request.env['HTTP_IF_MODIFIED_SINCE'] = 2.minutes.ago.rfc2822
    get :with_modified
    assert_equal 304, @response.status.to_i
    
        3
  •  4
  •   fotanus    10 年前

    好吧,这里有一点:

    在处理请求之前,请阅读Rails代码中与ETag相关的所有内容 别忘了设置:

    request.env["HTTP_IF_MODIFIED_SINCE"]
    request.env["HTTP_IF_NONE_MATCH"]
    

    因为它们是ETag测试所必需的。

        4
  •  1
  •   martinl    13 年前

    这一要点对rspec中的reetag测试非常有用-

    https://gist.github.com/brettfishman/3868277

        5
  •  0
  •   Manfred Stienstra    11 年前

    def calculate_etag(record, template)
      Digest::MD5.hexdigest(ActiveSupport::Cache.expand_cache_key([
        record,
        controller.send(:lookup_and_digest_template, template)
      ])).inspect
    end
    
    def set_cache_headers(modified_since: nil, record: nil, template: nil)
      request.if_modified_since = modified_since.rfc2822
      request.if_none_match = calculate_etag(record, template)
    end
    
    set_cache_headers(
      modified_since: 2.days.ago,
      record: @book,
      template: 'books/index'
    )
    
        6
  •  0
  •   dpneumo    7 年前

    至少在Rails5.2中,szeryf的解决方案失败了。这种变化确实有效:

    get action, parms
    assert_response 200, @response.code
    etag = @response.headers["ETag"]
    get action, parms, headers: { "HTTP_IF_NONE_MATCH": etag }
    assert_response 304, @response.code
    

    见导轨: https://guides.rubyonrails.org/testing.html#setting-headers-and-cgi-variables