2009-12-31 26 views
9

在我application_controller,我有下面的一组包括由url_for生成的所有路径的语言环境:如何设置功能测试(Rails)的区域default_url_options

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

我的资源路径则有:串流中删除= “/:locale”

在网站上正常工作。

但是,当涉及到我的功能测试中,:区域不与生成的URL传递,因此他们都失败。我可以通过添加区域设置的URL在我的测试中,像这样绕过它:

get :new, :locale => 'en' 

但我不希望有区域设置手动添加到每一个功能测试。

我尝试添加了default_url_options DEF以上test_helper,但它似乎没有任何效果。

有没有什么办法可以改变default_url_options以包括了所有的考试的语言环境?

谢谢。

回答

2

通过控制器测试情况如何生成的URL看似乎有不被直接的办法把它使用defualt_url_options。实际执行网址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调用,或把工艺方法称为方法。一种可能得到你正在寻找的方法可能是对过程方法进行alias_chain。

​​

你会想把它放到TestCase类之外的测试助手中,我想。让我知道它如何为你工作,我没有真正测试过,所以我们会看到。

+0

谢谢,约翰。这解决了上面的具体情况,似乎很好! 它似乎并没有解决的问题是TestCase如何解释命名路由,无论它们是在测试本身中,还是在应用程序中使用。例如,如果我有一个测试: redirect_to homepage_url 和homepath_url需要语言环境(map.homepage'/:locale',:controller =>'home'),当运行测试时出现错误, URL要求不满意(缺少“区域设置”)。再次,应用程序运行良好,因为default_url_options负责添加区域设置。有什么办法解决这个问题? – 2010-01-01 03:27:48

+0

我想补充一句,如果这只是测试本身的一个问题,那就不会那么糟糕。无论何时在测试中使用命名路由,我都可以添加区域设置。但问题是,无论何时在我的应用程序中使用命名路由时,它也会生成一个错误(并且我不希望每次都改变所有这些或指定区域设置,这样我的测试将运行)。 – 2010-01-01 03:34:22

+0

啊,我没有意识到它也发生在你的应用中。我刚刚遇到了一张灯塔,可能会帮助你一点点(似乎仍然是一个问题,但有一些解决办法)https://rails.lighthouseapp.com/projects/8994/tickets/1251-default_url_options-cant -be-used-named-routes – 2010-01-02 01:23:45

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 
1

我就遇到了这个问题,一个失败的黄瓜测试。 我使用的语言环境中的URL参数,即http://mysite.com/home?locale=he

我要做的,以应付这是从URL测试期间根据我的使用环境定义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 
+0

我不确定这是否暴露了某些边缘情况,但对我来说这似乎是一种优雅的解决方案。 – Jaryl 2011-06-03 04:05:27

1

我想出了一个针对这个问题的较少侵入性的解决方案。

setup :set_default_locale 

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

这种解决方案的优点是,它意味着你只能在默认的语言环境参数适用于某些测试用例,这样你就可以测试,例如,重定向策略本身。

7

在轨道3.1稳定分支,所述process method现在是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类中。

+0

Martin Carel在http://www.ruby-forum.com/topic/3448797上列出了这个方法,他还添加了另一个方法:'module ActionDispatch :: Assertions :: RoutingAssertions def assert_recognizes_with_default_locale(expected_options,path, extras = { },message = nil) expected_options = {:locale => I18n.default_locale.to_s }。合并(expected_options || {}) assert_recognizes_without_default_locale(expected_options,路径, 演员,消息) 端 alias_method_chain:assert_recognizes,:DEFAULT_LOCALE end' – wintersolutions 2012-02-06 15:14:54

+1

我还表示,修改'assert_recognizes'方法是一个** **欺骗。事实上,我认为不要模仿你正在测试的代码(就像在'Behavior'模块中添加一个方法的情况一样),而是破解你的测试工具。 – 2012-02-08 14:22:55

3

如果任何人使用此使用Rails 4.0,在process方法参数的顺序发生了变化,所以你需要使用这个更新补丁(基于@马丁 - 卡乐的回答,只是用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 

希望帮助任何人停留在这个问题上。

2

alias_method_chaindeprecated in Rails 5,它似乎行为过程方法已更改。

这里是我的上述马丁卡雷尔的回答修改,适应了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的专家,所以如果事情能在这个答案得到改善,让我知道,我会改变它。

+0

是的!这是解决方案,并添加到每个测试我想要定义一个不同的区域'before:context do I18n.locale =:ca end'我可以测试每个circunstance所需的任何区域设置。使用rails 5.1.4.rc1 – 2017-11-22 11:16:40

+0

我加了'if参数[:params] .nil?除非I18n.locale.nil?....'''''''params] = {} end'''以避免参数崩溃 – 2017-11-22 13:04:46

3

对于导轨5,我发现这个简单的解决方案 在test_helper.rb中

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

感谢您的回答,它为我工作。虽然我想知道是否有任何方法使用ApplicationController中的自定义default_url_options,因为编写两次相同的配置没有任何意义。 – afaundez 2017-07-29 22:18:51

+0

这在Rails 5.1.4中适用于我。 – taylorthurlow 2018-03-01 22:31:49

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 
相关问题