Никакой маршрут не соответствует анонимному контроллеру rspec
Основываясь на моем понимании rspec spec, я бы ожидал, что следующий пример пройдет.
describe ApplicationController do
controller do
def test
end
end
it "calls actions" do
get :test
end
end
Вместо этого он терпит неудачу:
No route matches {:controller=>"anonymous", :action=>"test"}
Я даже попытался определить маршрут для "анонимного" контроллера в файле маршрутов, но безрезультатно. Здесь что-то не хватает? Это должно работать, не так ли?
Ответы
Ответ 1
У меня была аналогичная проблема. В моем случае решение включало параметр: id в запросе get в тесте.
т.е.
get :test, :id => 1
Проверьте свои маршруты и посмотрите, отсутствует ли у вас определенный параметр (возможно: id), а затем добавьте это к тесту.
Ответ 2
Чтобы использовать пользовательские маршруты в спецификации анонимного контроллера, вам необходимо изменить маршрут, установленный перед блоком. RSpec уже устанавливает маршруты RESTful, используя resources :anonymous
в переднем блоке, и восстанавливает исходные маршруты в блоке after. Поэтому, чтобы ваши собственные маршруты просто нарисовали призыв на @routes
и добавьте то, что вам нужно.
Вот пример из ApplicationController
spec, который проверяет rescue_from CanCan::AccessDenied
require 'spec_helper'
describe ApplicationController
controller do
def access_denied
raise CanCan::AccessDenied
end
end
before do
@routes.draw do
get '/anonymous/access_denied'
end
end
it 'redirects to the root when access is denied' do
get :access_denied
response.should redirect_to root_path
end
it 'sets a flash alert when access is denied' do
get :access_denied
flash.alert.should =~ /not authorized/i
end
end
Обновление
Обработка для этого была улучшена где-то вокруг RSpec 2.12. Если вы используете > 2.12, вам больше не нужно подключаться к @routes
.
Нарисовать пользовательские маршруты для анонимных контроллеров
Ответ 3
У меня такая же проблема, я прочитал код метода controller
, который является этим (определяется здесь):
def controller(base_class = nil, &body)
base_class ||= RSpec.configuration.infer_base_class_for_anonymous_controllers? ?
controller_class :
ApplicationController
metadata[:example_group][:described_class] = Class.new(base_class) do
def self.name; "AnonymousController"; end
end
metadata[:example_group][:described_class].class_eval(&body)
# ADD ROUTES IN BEFORE BLOCK
before do
@orig_routes, @routes = @routes, ActionDispatch::Routing::RouteSet.new
@routes.draw { resources :anonymous } # <==== HERE ARE THE ROUTES
end
after do
@routes, @orig_routes = @orig_routes, nil
end
end
Комментарии в верхнем регистре кода являются моими, по существу, вы можете использовать только стандартные успокоительные маршруты при использовании этого метода. Также вы не можете использовать пользовательские маршруты в вашем файле routes.rb
, так как они перезаписываются для всего примера и восстанавливаются после него.
Ответ 4
Кажется, что rspec дает вам набор маршрутов RESTful для использования. Таким образом, если вы используете только стандартные имена действий в своем анонимном контроллере, вы не получите эту проблему. На сегодняшний день у меня никогда не было причины использовать ничего, кроме "индекса".
describe ApplicationController do
describe 'respond_with_foo' do
controller do
def index
respond_with_foo
end
end
it 'should respond with foo' do
get :index
response.should be_foo
end
end
end
Ответ 5
У меня была такая же проблема и я нашел решение, которое сработало для меня. Ключ состоит в том, чтобы наметить эти маршруты в самой тестовой спецификации:
require 'spec_helper'
describe ApplicationController do
#Base class should be inferred
controller do
def not_found
raise ActiveRecord::RecordNotFound
end
end
def with_error_routing
with_routing do |map|
map.draw do
get '/not_found' => "anonymous#not_found", :as => :not_found
end
yield
end
end
describe "handling ActiveRecord::RecordNotFound" do
it "renders the 404 template" do
with_error_routing do
get :not_found
response.should render_template 'error/404'
end
end
end
end
Ответ 6
Мне удалось обойти это со следующим патчем:
module RSpec::Rails
module ControllerExampleGroup
module ClassMethods
def controller(base_class = nil, &body)
base_class ||= RSpec.configuration.infer_base_class_for_anonymous_controllers? ?
controller_class :
ApplicationController
metadata[:example_group][:described_class] = Class.new(base_class) do
def self.name; "AnonymousController"; end
end
metadata[:example_group][:described_class].class_eval(&body)
######## PATCH START ########
custom_routes = @custom_routes # Copy over routes to local variable so it will be accessible
before do
@orig_routes, @routes = @routes, ActionDispatch::Routing::RouteSet.new
if custom_routes # if this was set then pass that to the draw function
@routes.draw &custom_routes
else
@routes.draw { resources :anonymous } # else do what it used to do before
end
######### PATCH END #########
routes = @routes
described_class.send(:define_method, :_routes) { routes }
end
after do
@routes, @orig_routes = @orig_routes, nil
end
end
######## PATCH START ########
def custom_routes &block
@custom_routes = block
end
######### PATCH END #########
end
end
конец
Требовать, чтобы файл в вашем spec_helper, а затем в вашем тесте просто:
describe ApplicationController do
describe 'respond_with_foo' do
custom_routes do
get :bar, controller: :anonymous, action: :bar
end
controller do
def index
respond_with_foo
end
end
it 'should respond with foo' do
get :index
response.should be_foo
end
end
end
В случае, если кто-нибудь спросит, я протестировал этот код, указав infer_base_class_for_anonymous_controllers значение false.