我无法使用minitest在我的Rails 4.2应用程序中成功测试自定义HTTP变量 - 出于某种原因,Rails似乎根本无法识别它们。
我有以下测试:
require "test_helper"
describe ApplicationController do
tests HomeController
before do
cookies[:locale] = "ru"
request.headers["Accept-Language"] = "zh-cn, en-us"
request.headers["CloudFront-Viewer-Country"] = "FR"
I18n.default_locale = :en
end
it "sets locale from URL params first" do
get :index, locale: "de"
I18n.locale.must_equal :de
end
it "sets locale from a cookie second" do
get :index
I18n.locale.must_equal :ru
end
it "sets locale from Accept-Language header third" do
cookies.delete :locale
get :index
I18n.locale.must_equal :"zh-CN"
end
it "sets locale from CloudFront-Viewer-Country header last" do
cookies.delete :locale
request.headers["Accept-Language"] = nil
get :index
I18n.locale.must_equal :fr
end
end
和相应的控制器:
class ApplicationController < ActionController::Base
# Prevent CSRF attacks by raising an exception.
# For APIs, you may want to use :null_session instead.
protect_from_forgery with: :exception
before_filter :set_locale
def default_url_options(options = {})
{ locale: I18n.locale }.merge options
end
private
def set_locale
I18n.locale = params[:locale] ||
cookies[:locale] ||
extract_locale_from_accept_language_header ||
set_locale_from_cloudfront_viewer_country ||
I18n.default_locale
unless request.fullpath =~ /^\/(?:[a-z]{2,2})(?:[-|_](?:[A-Z]{2,2}))?/
redirect_to %(#{request.protocol}#{request.host}/#{I18n.locale}#{request.fullpath unless request.fullpath == "/"}), status: :found
end
end
def extract_locale_from_accept_language_header
if request.env["Accept-Language"]
request.env["Accept-Language"].scan(/(?:[a-z]{2,2})(?:[-|_](?:[A-Z]{2,2}))?/i).first
end
end
def set_locale_from_cloudfront_viewer_country
case request.env["CloudFront-Viewer-Country"]
when "FR"
return :fr
else
return I18n.default_locale
end
end
end
最后两个测试失败,因为Rails似乎无法识别我设置的HTTP头变量,并且所有内容都属于默认语言环境:
Failure:
ApplicationController#test_0004_sets locale from CloudFront-Viewer-Country header last [/Users/aporter/Developer/com/wavetronix/www/test/controllers/application_controller_test.rb:33]
Minitest::Assertion: Expected: :fr
Actual: :en
Failure:
ApplicationController#test_0003_sets locale from Accept-Language header third [/Users/aporter/Developer/com/wavetronix/www/test/controllers/application_controller_test.rb:26]
Minitest::Assertion: Expected: :"zh-CN"
Actual: :en
如果我将Accept-Language
更改为HTTP_ACCEPT_LANGUAGE
,那么 测试会通过。
根据Rails documentation,我的测试应该有效。我用几种不同的方式搜索这个问题寻找答案然后空洞。 Stack Overflow上有一些与此类似的问题,但这些问题的答案和建议都没有解决我的问题。
我错过了什么?
环境:
答案 0 :(得分:6)
Rails通过以下方式为自定义HTTP标头设置request.env
变量:
因此,您可以在测试中设置request.headers["Accept-Language"]
,并在控制器中使用request.env["HTTP_ACCEPT_LANGUAGE"]
访问该值。同样,您在测试中设置了request.headers["CloudFront-Viewer-Country"]
,并在控制器中使用request.env["HTTP_CLOUDFRONT_VIEWER_COUNTRY"]
访问该值。
答案 1 :(得分:1)
Rails测试指南告诉我们Setting Headers:
“HTTP头和CGI变量可以直接在@request实例变量上设置:...”
所以你需要这样写:
@request.headers["Accept-Language"] = "zh-cn, en-us"
我认为,如果您不在before
方法中设置标头,而是直接在测试中,则会更好。因此,每次只设置此测试所需的标头。而且您不需要先设置cookie,然后将其删除。