繁体   English   中英

如何为功能测试(Rails)设置语言环境 default_url_options

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM