Маршрут не соответствует анонимному контроллеру rspec - PullRequest
28 голосов
/ 11 августа 2011

Исходя из моего понимания спецификации rspec , я ожидал бы, что следующий пример пройдет.

describe ApplicationController do

  controller do
    def test
    end
  end

  it "calls actions" do
    get :test
  end

end

Вместо этого произойдет сбой с:

No route matches {:controller=>"anonymous", :action=>"test"}

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

Ответы [ 6 ]

24 голосов
/ 16 февраля 2013

Чтобы использовать пользовательские маршруты в спецификации анонимного контроллера, необходимо изменить маршрут, заданный в блоке before.RSpec уже устанавливает маршруты RESTful, используя resources :anonymous в блоке before, и восстанавливает исходные маршруты в блоке after.Поэтому, чтобы получить свои собственные маршруты, просто наберите draw на @routes и добавьте то, что вам нужно.

Вот пример из спецификации ApplicationController, которая тестирует 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.

Рисовать пользовательские маршруты для анонимных контроллеров

21 голосов
/ 21 августа 2011

У меня была похожая проблема.В моем случае решение включало параметр: id в запрос на получение в тесте.

Т.е.

get :test, :id => 1

Проверьте ваши маршруты и посмотрите, не пропущен ли какой-либо параметр (возможно:id), затем добавьте это к тесту.

3 голосов
/ 16 ноября 2012

Кажется, что rspec дает вам набор маршрутов RESTful для использования. Таким образом, если вы используете только стандартные имена действий в своем анонимном контроллере, у вас не возникнет этой проблемы. На сегодняшний день у меня никогда не было причин использовать что-либо кроме «index».

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
3 голосов
/ 29 сентября 2012

У меня та же проблема, я прочитал код метода 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

Мои комментарии в верхнем регистре в моем коде,по существу, вы можете использовать только стандартные restful маршруты при использовании этого метода.Также вы не можете использовать пользовательские маршруты в файле routes.rb, поскольку они перезаписываются для всего примера и восстанавливаются после него.

1 голос
/ 03 ноября 2012

У меня была та же проблема, и я нашел решение, которое хорошо сработало для меня.Ключ заключается в том, чтобы наметить эти маршруты в самой тестовой спецификации:

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
0 голосов
/ 08 января 2013

Мне удалось обойти это с помощью следующего патча:

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

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

На случай, если кто-нибудь спросит, я протестировал этот код с установленным в false значением infer_base_class_for_anonymous_controllers.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...