2011-10-07 45 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