如何在Rails 3.1可安装引擎中测试路由

我正在尝试为可安装的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版本中修复了这个问题,所以我已经相应地更改了我接受的答案。

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

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

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

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

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

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

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 

这对我有用:

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

对我来说,这是迄今为止所有参与者的评论组合。

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

  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 ' 

所以我从get('/')切换到{ :get => '/' } ,事情开始变得很好。 不知道为什么。 根据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 ' 

所以我补充说:

 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 ' 

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

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

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

下一部分很奇怪。 为特定小部件添加另一个测试后,该小部件使用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 # # ./spec/views/mozoo/widgets/show.html.haml_spec.rb:7:in `block (2 levels) in ' 

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

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

和BAM! 它过去了。 谢谢@sam-soffes。 使这个奇怪的是,稍后在创建此注释时,我删除了该配置条目以尝试并返回错误,我无法通过删除配置条目来重现错误。 哦,我继续前进。 希望这个冗长的帐户可以帮助某些人。

根据这个答案,我选择了以下解决方案:

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

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