如何测试Rails的ETag缓存?

8

我有一个高度依赖ETags的控制器,是否可能用单元测试来覆盖它呢?

我的做法是:如果页面不过时(即仍然新鲜),就向响应添加一些头信息。

但无论我有多少个类似的请求,当我尝试进行测试(使用rspec),我仍然收到200 OK而不是304,并且我的头信息没有被修改。此外,如果我跟踪request.fresh?(response),它总是返回false。

然而,在浏览器中完全正常。

我已经尝试过设置ActionController::Base.perform_caching = true,但整个情况并没有改变。

谢谢!

6个回答

12

以下是如何测试第二个请求是否返回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

5

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

哦,那是很久以前的问题了。我认为它仍然是Rails 2.3.5版本,所以自那时以来可能发生了很多变化。 - 0100110010101

4

好的,这里有一个要点:

在发送请求之前,请阅读与Rails代码中ETags相关的所有内容,并不要忘记设置:

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

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


你好,可以详细解释一下这是什么意思吗?当我设置 request.env 时,它仍然不包含 etag。 - Tosa
@Tosa,请看下面的答案,其中有一些想法(我无法在评论中发布太多代码)。 - szeryf
1
这怎么能算是答案,更别说被采纳的答案了?你说要做一些研究并设置一些环境变量,但你没有说明应该研究什么以及应该将环境变量设置为什么。 - d_rail

1

1

0
Rails 4.2现在也考虑模板的摘要。对我来说,以下方法有效:
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'
)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接