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

时间:2009-12-31 22:38:15

标签: ruby-on-rails testing internationalization

在我的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以包含我所有测试的区域设置?

感谢。

10 个答案:

答案 0 :(得分:7)

在Rails 3.1-stable分支中,process method现在位于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类中。

答案 1 :(得分:6)

对于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

答案 2 :(得分:3)

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

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

答案 3 :(得分:2)

查看控制器测试用例如何生成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类之外的测试帮助器中。让我知道它对你有用,我还没有真正测试过,所以我们会看到。

答案 4 :(得分:2)

alias_method_chaindeprecated in Rails 5,似乎行为处理方法已更改。

这是我对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的专家,所以如果在这个答案中可以改进一些内容,请告诉我,我会改变它。

答案 5 :(得分:1)

我遇到了一个失败的黄瓜测试问题。 我在网址中使用locales作为参数,即http://mysite.com/home?locale=he

我要做的是通过根据我使用的环境定义default_url_options,在测试期间从网址中删除所有与语言环境相关的内容:

  # 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

答案 6 :(得分:1)

我已经提出了一个针对这个问题的侵入性较小的解决方案。

setup :set_default_locale 

def set_default_locale
  def @request.query_parameters
    {:locale => "en"}.merge(@query_parameters)
  end
end

此解决方案的优点是,它意味着您只能将默认语言环境参数应用于某些测试用例,因此您可以测试,例如,重定向策略本身。

答案 7 :(得分:1)

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

答案 8 :(得分:0)

通过集成测试,我发现上面的猴子补丁需要不同,这对我有用(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

答案 9 :(得分:0)

我尝试了很多例子,但是只有这个例子对我有帮助。简洁明了。将此代码段添加到test.rb:

Rails.application.configure do
  # ... other config ...

  routes.default_url_options[:locale] = :en
end

在Rails 5.1.4上运行