2011-10-07 69 views
18

我正在尝试为可挂载rails 3.1引擎编写一些路由规范。我有工作模型和控制器规格,但我无法弄清楚如何指定路线。如何在Rails 3.1可挂载引擎中测试路由

对于采样引擎,“暴躁”,每一个方法,我尝试了同样的错误两端:

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

我都试过Rspec的与测试::单位语法(规格/路由/ 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 

我已经制定了正确的路线(配置/ routes.rb中):

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

,并安装它们在虚拟应用程序(规格/空/配置/ routes.rb中):

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

和运行rails server,并要求http://localhost:3000/testy/的作品就好了。

我是否缺少任何明显的东西,或者这只是没有妥善烘焙到框架呢?

更新:正如@andrerobot指出的那样,rspec的人已经在版本2.14中解决了这个问题,所以我已经改变了我接受的答案。

+0

你看到的路线,当你运行rake路线? –

+0

你是否在index_routing_spec.rb中需要'spec_helper'? – squarism

+0

rake路径在rails 3.1引擎中不起作用。也许这是一个错误,但它在这里解释:http://stackoverflow.com/questions/7431687/listing-rake-routes-for-a-mountable-rails-3-1-engine –

回答

11

由于RSpec的2.14,您可以使用以下方法:

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

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

+0

感谢您的更新!我使用rspec 2.14和rails 4.0创建了一个可挂载的引擎,并且像魅力一样工作。我改变了我接受的答案。 –

+1

如果我需要引擎的路由和main_app的路由,该怎么办? – Jwan622

10

尝试用以下块之前添加:

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

这工作对我来说,作为路由规范使用顶层实例变量,以测试他们的路线。

+0

谢谢 - 这是非常接近的,但用引擎的路线替换'默认'路线也要求我改变我的测试,所以我upvoted你的答案,因为它是我需要的最后线索。 –

4

这为我工作:

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

不幸的是,包括url帮助者并没有改变我所看到的错误:ActionController :: RoutingError:没有路由匹配“/ testy” –

11

从史蒂芬·安德森的回答让我最那里的方式,但需要相对于发动机提出的要求,而不是应用程序 - 可能是因为这种技术用引擎的路线替换应用程序的路线,所以现在一切都与引擎有关。这对我来说似乎有点脆弱,但我还没有看到有效的另一种方式。如果有人发布了更干净的方式,我会很乐意接受该答案。

在“虚拟”的应用程序,如果发动机安装如下(规格/虚设/配置/ routes.rb中):

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

以下规范将正确使用测试发动机的根路径两者的RSpec和测试::单位语法(规格/路由/ 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 
+0

这个。我希望能够在我的规格中使用类似'get:'/ testy /''的东西来更贴近地匹配我实际安装引擎的位置。但这似乎不可能,这个答案似乎是目前最好的方式来通过规范。 – dojosto

+0

这对我有效,但对于test :: unit,我将@routes赋值放置在我的设置函数中。 – mkrinblk

1

对于我来说,这是迄今所涉及的几乎每个人的意见相结合。

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

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 => '/' },事情开始伟大的工作。不知道为什么。根据lib/rspec/rails/matchers/routing_matchers.rb L102-105,没有什么区别,但它对我有所不同。无论如何,谢谢@卡梅伦 - 波普。

接下来,我增加了一个非常简单,非常类似的测试与上面:

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") 

和中提琴,它通过。谢谢@史蒂文安德森。

接下来的部分很奇怪。添加其他测试其使用的widget_path网址助手名为路径特定的控件后:

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

测试及时blowd在我身上有:

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 config条目:

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

和BAM!它通过了。谢谢@ sam-soffes。造成这种情况的奇怪之处在于,在创建此评论后,我删除了该配置条目以尝试并返回错误,并且我无法简单地通过删除配置条目来重现错误。哦,我正在继续前进。希望这个冗长的帐户可以帮助某人。

0

基于this答案,我选择了以下解决方案:

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

额外的好处是,你不需要在每一个控制器规格的before(:each)块。

+1

这不适合我。任何想法为什么?如果我在测试本身之前添加它,它似乎工作。 – Karan