如何为function测试设置locale default_url_options(Rails)

在我的application_controller中,我有以下设置来包含具有url_for生成的所有路径的语言环境:

def default_url_options(options={}) { :locale => I18n.locale } end 

我的资源路由有一个:path_prefix =“/:locale”

在网站上正常工作。

但是当涉及到我的function测试时,:locale不会与生成的url一起传递,因此它们都会失败。 我可以通过在我的测试中将语言环境添加到url来解决它,如下所示:

  get :new, :locale => 'en' 

但我不想手动将语言环境添加到每个function测试中。

我尝试将default_url_options def添加到test_helper上面,但似乎没有效果。

有什么办法可以更改default_url_options以包含我所有测试的语言环境?

谢谢。

通过查看控制器测试用例如何生成URL,似乎没有直接的方法让它使用defualt_url_options。 实际执行url creationg的主要块(在测试中)看起来像这样( 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 

这由进程方法调用,而进程方法又由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 3.1-stable分支中, 流程方法现在位于Behavior模块中。 所以这里的代码对我有用(与John Duff的答案略有不同):

 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 

我确保在运行specs / tests之前调用此代码。 放在test_helper类中的好地方。

对于Rails 5,我在test_helper.rb找到了这个简单的解决方案,基于action_dispatch / testing / integration.rb

 module ActionDispatch::Integration class Session def default_url_options { locale: I18n.locale } end end end 

如果有人在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 

希望能帮助任何人解决这个问题。

在Rails 5中不推荐使用 alias_method_chain ,似乎行为处理方法已经改变。

这是我对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