Как тестировать рельсы Etag кэширование?
-
27-09-2019 - |
Вопрос
Можно ли покрыть мою контроллер, который сильно опирается на Etags с модульными тестами?
Вот что я пытаюсь сделать: в случае, если бы страница не несвечивается (что означает, что это свежо), я добавляю некоторый заголовок для ответа.
Когда я пытаюсь проверить все это (RSPEC), независимо от того, сколько аналогичных запросов у меня есть, я все еще получаю 200 OK вместо 304, и мой заголовок не изменится. Кроме того, если я отслеживаю запрос. Ffresh? (Ответ), это всегда ложно.
Однако он прекрасно работает в браузере. Я уже пытался указать ActionController :: Base.perform_Caching = True, это не изменяет общую ситуацию.
Спасибо
Решение 3
Хорошо, вот точка:
Перед ударом запроса прочитайте все, что связано с Etags в коде Rails и не забудьте установить:
request.env["HTTP_IF_MODIFIED_SINCE"]
request.env["HTTP_IF_NONE_MATCH"]
Так как они необходимы для тестирования Etag.
Другие советы
Вот как вы можете проверить, если второй запрос возвращает 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
Рельсы хэши: 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
Этот сигнал очень полезен Re Etag Testing в RSPEC -
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'
)
По крайней мере, в рельсах 5,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
См. Руководства Rails: https://guides.rubyonrails.org/testing.html#setting-headers-and-cgi-variables.