Как протестировать маршруты в монтируемом движке Rails 3.1 - PullRequest
20 голосов
/ 07 октября 2011

Я пытаюсь написать некоторые спецификации маршрутизации для монтируемого двигателя 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 / rout.rb):

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

И смонтировал их в фиктивном приложении (spec / dummy / config / rout.rb):

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

И выполнение rails server и запрос http://localhost:3000/testy/ работает просто отлично.

Я что-то упускаю из виду, или это просто еще не запечено в рамках?

Обновление: Как указывает @andrerobot, люди rspec исправили эту проблему в версии 2.14, поэтому я соответственно изменил свой принятый ответ.

Ответы [ 6 ]

12 голосов
/ 04 июля 2013

Начиная с RSpec 2.14 вы можете использовать следующее:

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

Источник: https://github.com/rspec/rspec-rails/pull/668

11 голосов
/ 15 ноября 2011

Ответ от Стивена Андерсона дал мне большую часть пути, но запросы должны быть сделаны относительно движка, а не приложения - вероятно, потому что этот метод заменяет маршруты приложения маршрутами движка, так что все теперь относительно двигателя. Это кажется немного хрупким для меня, но я не видел другой способ, который работает. Если кто-то опубликует более понятный способ сделать это, я с радостью приму этот ответ.

В приложении 'dummy', если двигатель смонтирован следующим образом (spec / dummy / config / rout.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
11 голосов
/ 01 ноября 2011

Попробуйте добавить блок before со следующим:

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

Это сработало для меня, поскольку спецификации маршрутизации используют эту переменную экземпляра верхнего уровня для проверки своих маршрутов.

4 голосов
/ 10 ноября 2011

Это сработало для меня:

# spec_helper.rb
RSpec.configure do |config|
  config.include MyEngine::Engine.routes.url_helpers
end
1 голос
/ 13 марта 2013

На основании этого ответа я выбрал следующее решение:

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

Дополнительное преимущество заключается в том, что вам не нужно иметь before(:each) блок в каждом контроллере-спецификации.

1 голос
/ 30 мая 2012

Для меня это была комбинация комментариев почти всех участников.

Сначала я начал с этого простого теста:

  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 , разницы нет, но для меня это имеет значение. В любом случае, спасибо @ 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")

И альт, это прошло. Спасибо, Стивен-Андерсон.

Следующая часть странная. После добавления еще одного теста для определенного виджета, который использовал помощника url widget_path для именованного маршрута:

  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

И БАМ! Это прошло. Спасибо @ sam-soffes. Что делает это странным, так это то, что позже при создании этого комментария я удалил эту запись конфигурации, чтобы попытаться вернуть ошибку, и мне не удалось воспроизвести ошибку, просто удалив запись конфигурации. О, хорошо, я иду дальше. Надеюсь, этот скучный аккаунт кому-нибудь поможет.

...