Ответ 1
Так как RSpec 2.14 вы можете использовать следующее:
describe "test controller routing" do
routes { Testy::Engine.routes }
# ...
end
Я пытаюсь написать некоторые спецификации маршрутизации для монтируемого рельса 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 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
Ответ от Стивена Андерсона доставил мне большую часть пути, но запросы нужно сделать относительно двигателя, а не приложения - вероятно, потому, что эта техника заменяет маршруты приложений маршрутами движка, поэтому все сейчас относительно двигателя. Мне кажется немного хрупким, но я не видел другого способа, который работает. Если кто-то выскажет более чистый способ сделать это, я буду рад принять этот ответ.
В приложении '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 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
Попробуйте добавить блок до следующего:
before(:each) { @routes = Testy::Engine.routes }
Это сработало для меня, поскольку спецификации маршрутизации используют эту переменную экземпляра верхнего уровня для проверки своих маршрутов.
Это сработало для меня:
# 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 <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")
И альт, он прошел. Спасибо @steven-anderson.
Эта следующая часть нечетна. После добавления другого теста для конкретного виджета, который использовал помощник 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. Что делает это странным, так это то, что позже при создании этого комментария я удалил эту запись конфигурации, чтобы попытаться вернуть ее, и я не смог воспроизвести ошибку, просто удалив запись config. Хорошо, я двигаюсь дальше. Надеюсь, этот длинный счет поможет кому-то.
На основе этого ответа я выбрал следующее решение:
#spec/spec_helper.rb
RSpec.configure do |config|
# other code
config.before(:each) { @routes = MyEngine::Engine.routes }
end
Дополнительным преимуществом является то, что вам не нужно иметь блок before(:each)
в каждой спецификации контроллера.