![](/img/trans.png)
[英]Set locale via default_url_options for Rails tests (Rails 6 and newer)
[英]How to set locale default_url_options for functional tests (Rails)
在我的 application_controller 中,我有以下设置以包含由 url_for 生成的所有路径的语言环境:
def default_url_options(options={})
{ :locale => I18n.locale }
end
我的资源路由然后有一个 :path_prefix = "/:locale"
在网站上运行良好。
但是当涉及到我的功能测试时, :locale 没有与生成的 url 一起传递,因此它们都失败了。 我可以通过在我的测试中将语言环境添加到 url 来解决它,如下所示:
get :new, :locale => 'en'
但我不想手动将语言环境添加到每个功能测试中。
我尝试将上面的 default_url_options def 添加到 test_helper,但似乎没有效果。
有什么方法可以更改 default_url_options 以包含所有测试的语言环境?
谢谢。
对于 Rails 5,我在基于action_dispatch/testing/integration.rb 的test_helper.rb
找到了这个简单的解决方案
module ActionDispatch::Integration
class Session
def default_url_options
{ locale: I18n.locale }
end
end
end
在 Rails 3.1-stable 分支中, process 方法现在位于Behavior
模块中。 所以这是对我有用的代码(与约翰达夫的回答略有不同):
class ActionController::TestCase
module Behavior
def process_with_default_locale(action, parameters = nil, session = nil, flash = nil, http_method = 'GET')
parameters = { :locale => I18n.default_locale }.merge( parameters || {} )
process_without_default_locale(action, parameters, session, flash, http_method)
end
alias_method_chain :process, :default_locale
end
end
我确保在运行规范/测试之前调用此代码。 放置它的好地方是 test_helper 类。
如果有人在 Rails 4.0 中使用它, process
方法中的参数顺序已经改变,所以你需要使用这个更新的补丁(基于@martin-carel 的回答,只是将http_method
参数移到第二个参数):
class ActionController::TestCase
module Behavior
def process_with_default_locale(action, http_method = 'GET', parameters = nil, session = nil, flash = nil)
parameters = { :locale => I18n.locale }.merge( parameters || {} ) unless I18n.locale.nil?
process_without_default_locale(action, http_method, parameters, session, flash)
end
alias_method_chain :process, :default_locale
end
end
希望能帮助任何陷入这个问题的人。
我尝试了很多例子,但只有这个对我有帮助。 它简洁明了。 将此代码片段添加到 test.rb:
Rails.application.configure do
# ... other config ...
routes.default_url_options[:locale] = :en
end
适用于 Rails 5.1.4
查看控制器测试用例如何生成 url 似乎没有直接的方法让它使用 defualt_url_options。 实际执行 url 创建的主要块(在测试中)如下所示( http://github.com/rails/rails/blob/master/actionpack/lib/action_controller/test_case.rb ):
private
def build_request_uri(action, parameters)
unless @request.env['REQUEST_URI']
options = @controller.__send__(:rewrite_options, parameters)
options.update(:only_path => true, :action => action)
url = ActionController::UrlRewriter.new(@request, parameters)
@request.request_uri = url.rewrite(options)
end
end
这由 process 方法调用,而 process 方法又由 get、post、head 或 put 方法调用。 一种可能获得您正在寻找的内容的方法可能是 alias_chain 进程方法。
class ActionController::TestCase
def process_with_default_locale(action, parameters = nil, session = nil, flash = nil, http_method = 'GET')
parameters = {:locale=>'en'}.merge(parameters||{})
process_without_default_locale(action, parameters, session, flash, http_method)
end
alias_method_chain :process, :default_locale
end
你会想把它放在你的测试助手中,在我认为的 TestCase 类之外。 让我知道它是如何为你工作的,我还没有真正测试过它,所以我们会看到。
在 Rails 5 中不推荐使用alias_method_chain
,似乎 Behavior 过程方法已更改。
这是我对上述 Martin Carel 回答的修改,适用于 Rails 5。
RSpec.configure do |config|
module ActionController
class TestCase
module Behavior
module LocaleParameter
def process(action, parameters = {params: {}})
unless I18n.locale.nil?
parameters[:params][:locale] = I18n.locale
end
super(action, parameters)
end
end
prepend Behavior::LocaleParameter
end
end
end
end
我绝不是 Rails 或 Ruby 的专家,所以如果这个答案有什么可以改进的地方,请告诉我,我会改变它。
我在黄瓜测试失败时遇到了这个问题。 我在 url 中使用 locales 作为参数,即http://mysite.com/home?locale=he
为了解决这个问题,我所做的是在测试期间通过根据我使用的环境定义 default_url_options 来从 url 中删除所有与语言环境相关的内容:
# app/controllers/application_controller.rb
def default_url_options(options={})
logger.debug "default_url_options is passed options: #{options.inspect}\n"
ENV["RAILS_ENV"] != "cucumber" ? { :locale => I18n.locale } : {}
end
我想出了一个针对这个问题的侵入性较小的解决方案。
setup :set_default_locale
def set_default_locale
def @request.query_parameters
{:locale => "en"}.merge(@query_parameters)
end
end
该解决方案的优势在于,它意味着您只能将默认语言环境参数应用于某些测试用例,因此您可以测试例如重定向策略本身。
Ruby 5.1 再次发生了变化。 以下是对我有用的内容:
class ActionController::TestCase
module Behavior
module LocaleParameter
def process(action, params: {}, **args)
# Locale parameter must be a string
params[:locale] = I18n.locale.to_s
super(action, params: params, **args)
end
end
end
prepend Behavior::LocaleParameter
end
通过集成测试,我发现上面的猴子补丁需要不同,这对我有用(Rails 2.3.4):
class ActionController::Integration::Session
def url_for_with_default_locale(options)
options = { :locale => 'en' }.merge(options)
url_for_without_default_locale(options)
end
alias_method_chain :url_for, :default_locale
end
处理功能测试时不使用default_url_options
并且似乎没有办法在没有猴子补丁的情况下定义默认值( 2021 年 10 月 15 日的 master 分支)。
所以我设法通过覆盖test/test_helper.rb
文件中的ActionController::TestCase#process
方法来让它工作,如下所示:
class ActionController::TestCase
module DefaultParameters
def process(action, params: {}, **args)
params[:locale] ||= 'en'
super(action, params: params, **args)
end
end
prepend DefaultParameters
end
上述代码适用于 Rails 6.1.4,但可能需要对较早或未来的 Rails 版本进行一些调整。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.