【问题标题】:How to test routes in a Rails 3.1 mountable engine如何在 Rails 3.1 可安装引擎中测试路线
【发布时间】:2013-07-12 06:07:31
【问题描述】:

我正在尝试为可安装的 rails 3.1 引擎编写一些路由规范。我有工作模型和控制器规格,但我不知道如何指定路由。

对于示例引擎“testy”,我尝试的每种方法都以相同的错误结束:

 ActionController::RoutingError:
   No route matches "/testy"

我已经尝试过 Rspec 和 Test::Unit 语法 (spec/routing/index_routing_spec.rb):

describe "test controller routing" do
  it "Routs the root to the test controller's index action" do
    { :get => '/testy/' }.should route_to(:controller => 'test', :action => 'index')
  end

  it "tries the same thing using Test::Unit syntax" do
    assert_routing({:method => :get, :path => '/testy/', :use_route => :testy}, {:controller => 'test', :action => 'index'})
  end
end

我已经正确布置了路线(config/routes.rb):

Testy::Engine.routes.draw do
  root :to => 'test#index'
end

并将它们安装在虚拟应用程序中(spec/dummy/config/routes.rb):

Rails.application.routes.draw do
  mount Testy::Engine => "/testy"
end

运行rails server 并请求http://localhost:3000/testy/ 工作正常。

我是否遗漏了任何明显的东西,或者只是还没有正确融入框架?

更新:正如@andrerobot 指出的那样,rspec 人员已在 2.14 版中修复了此问题,因此我已相应地更改了我接受的答案。

【问题讨论】:

  • 你在运行 rake 路由时看到路由了吗?
  • 你在 index_routing_spec.rb 中有 require 'spec_helper' 吗?
  • rake 路由在 rails 3.1 引擎中不起作用。也许这是一个错误,但在这里解释:stackoverflow.com/questions/7431687/…
  • @squarism,我愿意。我忽略了将其包含在代码示例中

标签: ruby-on-rails ruby-on-rails-3 rspec2


【解决方案1】:

从 RSpec 2.14 开始,您可以使用以下内容:

describe "test controller routing" do
  routes { Testy::Engine.routes }
  # ...
end

来源:https://github.com/rspec/rspec-rails/pull/668

【讨论】:

  • 感谢您的更新!我使用 rspec 2.14 和 rails 4.0 创建了一个可安装的引擎,它的工作就像一个魅力。我已更改接受的答案。
  • 如果我需要引擎的路由和 main_app 的路由怎么办?
  • 问题是具体路由在虚拟应用的路由中。此解决方案不包含虚拟应用程序的路线,而是仅包含引擎的路线。
【解决方案2】:

尝试使用以下内容添加 before 块:

before(:each) { @routes = Testy::Engine.routes }

这对我有用,因为路由规范使用顶级实例变量来测试他们的路由。

【讨论】:

  • 谢谢 - 非常接近,但是用引擎的路线替换“默认”路线也需要我更改测试,所以我赞成你的答案,因为这是我需要的最后一条线索。
【解决方案3】:

Steven Anderson 的回答让我获得了大部分的成功,但是请求需要相对于引擎而不是应用程序发出 - 可能是因为这种技术用引擎的路线替换了应用程序的路线,所以现在一切都好了相对于发动机。这对我来说似乎有点脆弱,但我还没有看到另一种有效的方式。如果有人发布了一种更简洁的方法,我很乐意接受这个答案。

在“dummy”应用中,如果引擎安装如下(spec/dummy/config/routes.rb):

Rails.application.routes.draw do
  mount Testy::Engine => "/testy"
end

以下规范将使用 rspec 和 test::unit 语法 (spec/routing/index_route_spec.rb) 正确测试引擎的根路由:

require 'spec_helper'

describe "test controller routing" do
  before(:each) { @routes = Testy::Engine.routes }

  it "Routes the root to the test controller's index action" do
    { :get => '/' }.should route_to(:controller => 'testy/test', :action => 'index')
  end

  it "tries the same thing using Test::Unit syntax" do
    assert_routing({:method => :get, :path => '/'}, {:controller => 'testy/test', :action => 'index'})
  end
end

【讨论】:

  • 这个。我希望能够在我的规格中使用get: '/testy/' 之类的东西,以更接近地匹配我实际安装引擎的位置。但这似乎是不可能的,而且这个答案似乎是目前通过规范的最佳方式。
  • 这对我有用,但对于 test::unit 我将@routes 分配放在我的设置函数中。
  • @dojosto 你找到get: '/testy/' 请求的解决方案了吗?我知道这是一个旧答案,但我今天偶然发现了确切的问题
【解决方案4】:

这对我有用:

# spec_helper.rb
RSpec.configure do |config|
  config.include MyEngine::Engine.routes.url_helpers
end

【讨论】:

  • 不幸的是,包括 url 助手并没有改变我看到的错误:ActionController::RoutingError: No route matches "/testy"
【解决方案5】:

对我来说,到目前为止,几乎所有参与的人都将 cmet 组合在一起。

首先,我从这个简单的测试开始:

  it "routes / to the widgets controller" do
    get('/').should route_to("mozoo/widget#index")
  end

这导致:

Failures:
  1) Mozoo::WidgetController GET widget index routes / to the widgets controller
     Failure/Error: get('/').should route_to("mozoo/widget#index")
     ActionController::RoutingError:
       No route matches {:controller=>"mozoo/widget", :action=>"/"}
     # ./spec/controllers/mozoo/widget_controller_spec.rb:9:in `block (3 levels) in <module:Mozoo>'

所以我从get('/') 切换到{ :get =&gt; '/' },一切都开始运转良好。不知道为什么。根据lib/rspec/rails/matchers/routing_matchers.rb L102-105,没有区别,但对我来说有区别。无论如何,谢谢@cameron-pope。

接下来,我添加了另一个非常简单且与上面非常相似的测试:

it "routes root_path to the widgets controller" do
  { :get => root_path }.should route_to("mozoo/widget#index")
end

并且收到此错误:

Failures:
  1) Mozoo::WidgetController GET widget index routes root_path to the widgets controller
     Failure/Error: { :get => '/mozoo' }.should route_to("mozoo/widget#index")
       No route matches "/mozoo"
     # ./spec/controllers/mozoo/widget_controller_spec.rb:14:in `block (3 levels) in <module:Mozoo>'

所以我添加了这个:

before(:each) { @routes = Mozoo::Engine.routes }

得到一个更好/不同的错误:

Failures:
  1) Mozoo::WidgetController GET widget index routes root_path to the widgets controller
     Failure/Error: { :get => root_path }.should route_to("mozoo/widget#index")
       The recognized options <{"controller"=>"mozoo/widget", "action"=>"index", "section"=>"mozoo"}> did not match <{"controller"=>"mozoo/widget", "action"=>"index"}>, difference: <{"section"=>"mozoo"}>.
       <{"controller"=>"mozoo/widget", "action"=>"index"}> expected but was
       <{"controller"=>"mozoo/widget", "action"=>"index", "section"=>"mozoo"}>.
     # ./spec/controllers/mozoo/widget_controller_spec.rb:14:in `block (3 levels) in <module:Mozoo>'

从那里,我更改了我的测试以包含该部分(我的引擎所在的命名空间):

{ :get => root_path }.should route_to(:controller => "mozoo/widget", :action => "index", :section => "mozoo")

还有中提琴,它通过了。谢谢@steven-anderson。

接下来的部分很奇怪。在为使用 widget_path url helper 命名路由的特定小部件添加另一个测试后:

  it "will successfully serve the widget show page" do
    visit widget_path(:foobar)
    response.should be_success
  end

测试很快就让我大吃一惊:

Failures:
  1) GET bubble_summary_row widget will have the content section properly scoped
     Failure/Error: visit widget_path(:bubble_summary_row)
     NoMethodError:
       undefined method `widget_path' for #<RSpec::Core::ExampleGroup::Nested_3:0x0000010748f618>
     # ./spec/views/mozoo/widgets/show.html.haml_spec.rb:7:in `block (2 levels) in <module:Mozoo>'

所以我添加了以下 spec_helper 配置条目:

RSpec.configure do |config|
  config.include Testy::Engine.routes.url_helpers
end

还有 BAM!它通过了。谢谢@sam-soffes。奇怪的是,后来在创建此评论时,我删除了该配置条目以尝试恢复错误,但我无法仅通过删除配置条目来重现该错误。哦,好吧,我继续前进。希望这个冗长的帐户可以帮助某人。

【讨论】:

    【解决方案6】:

    根据this 的回答,我选择了以下解决方案:

    #spec/spec_helper.rb
    RSpec.configure do |config|
     # other code
     config.before(:each) { @routes = MyEngine::Engine.routes }
    end
    

    额外的好处是,您不需要在每个控制器规范中都有 before(:each) 块。

    【讨论】:

    • 这对我不起作用。知道为什么吗?如果我在测试本身的行之前添加它,它似乎可以工作。
    猜你喜欢
    • 2011-11-19
    • 1970-01-01
    • 1970-01-01
    • 2011-11-17
    • 2012-09-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多