Подтвердить что ты не робот

Никакой маршрут не соответствует анонимному контроллеру 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"}

Я даже попытался определить маршрут для "анонимного" контроллера в файле маршрутов, но безрезультатно. Здесь что-то не хватает? Это должно работать, не так ли?

4b9b3361

Ответ 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.