Rails 控制器 rspecs 因规范/控制器的 RoutingError 失败,但通过个别测试 [英] Rails controller rspecs fail with RoutingError for spec/controllers but pass for individual tests

查看:52
本文介绍了Rails 控制器 rspecs 因规范/控制器的 RoutingError 失败,但通过个别测试的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的控制器规格在我一个接一个运行时通过,但当我将它们作为控制器一起运行时都失败了.

My controller specs are passing when I run them one by one but are all failing when I run them together as controllers.

$rspec spec/controllers

22) SubjectsController GET index assigns all subjects as @subjects
     Failure/Error: get :index, {}
     ActionController::RoutingError:
       No route matches {:controller=>"subjects"}
     # ./spec/controllers/subjects_controller_spec.rb:13:in `block (3 levels) in <top (required)>'

我的猜测是它一定与数据库清理有关,但我不确定在控制器规范中排除路由错误的最佳方法.

My guess is it must be something to do with database cleaner but I'm not sure best way to troubleshoot routing errors in controller specs.

宝石文件

gem 'rails', '3.2.13'
gem 'mysql2', '0.3.13'
gem 'devise', '2.2.3'
...
...
group :development, :test do
  gem 'rspec-rails', '~> 2.99'
  gem 'webrick',    '~> 1.3'
  gem 'rails-erd', '~> 1.1'
  gem 'bullet', '~> 4.6'
  gem 'pry-rails', '~> 0.3'
  gem 'factory_girl_rails', '~> 4.4'
  gem 'faker', '~> 1.2'
end

group :test do
  gem 'cucumber-rails', :require => false
  gem 'capybara', '~> 2.2.1'
  gem 'database_cleaner', '~> 1.3.0'
  gem 'launchy', '~> 2.4.2'
  gem 'shoulda-matchers', '~> 2.6.1'
  gem 'vcr', '~> 2.9.2'
  gem 'webmock', '~>  1.13.0'
  gem 'zeus', '~> 0.13.3'
end

spec/spec_helper.rb

spec/spec_helper.rb

# This file is copied to spec/ when you run 'rails generate rspec:install'
ENV["RAILS_ENV"] = 'test'
require File.expand_path("../../config/environment", __FILE__)
require 'rspec/rails'
require 'rake'
require 'sidekiq/testing'

Sidekiq::Logging.logger = nil


# Requires supporting ruby files with custom matchers and macros, etc,
# in spec/support/ and its subdirectories.
Dir[Rails.root.join("spec/support/**/*.rb")].each {|f| require f}

RSpec.configure do |config|
  # ## Mock Framework
  #
  # If you prefer to use mocha, flexmock or RR, uncomment the appropriate line:
  #
  # config.mock_with :mocha
  # config.mock_with :flexmock
  # config.mock_with :rr
  config.mock_with :rspec

  # Only run tests that have this filter, if it exists
  # config.filter_run :debug => true

  # Run all the tests when all the tests are filtered
  # config.run_all_when_everything_filtered = true

  config.treat_symbols_as_metadata_keys_with_true_values = true

  # Remove this line if you're not using ActiveRecord or ActiveRecord fixtures
  # config.fixture_path = "#{::Rails.root}/spec/fixtures"

  # If you're not using ActiveRecord, or you'd prefer not to run each of your
  # examples within a transaction, remove the following line or assign false
  # instead of true.
  config.use_transactional_fixtures = false

  # If true, the base class of anonymous controllers will be inferred
  # automatically. This will be the default behavior in future versions of
  # rspec-rails.
  config.infer_base_class_for_anonymous_controllers = false

  config.include FactoryGirl::Syntax::Methods
  config.include Devise::TestHelpers, :type => :controller
  config.extend ControllerMacros, :type => :controller

  OmniAuth.config.test_mode = true

  OmniAuth.config.mock_auth[:facebook] = OmniAuth::AuthHash.new( {
      provider: 'facebook',
      uid: '123545',
      info: {
            first_name: 'John',
            last_name: 'Doe',
            email: 'johndoe@gmail.com'
        },
      credentials: {
          token: "123456",
          expires_at: Time.now + 1.week
      },
      extra: {
          raw_info: {
              gender: 'male'
          }
      }
  })

  # silence rspec 3 deprecation warnings
  config.expose_current_running_example_as :example
  config.infer_spec_type_from_file_location!

  def login(user)
    @request.env["devise.mapping"] = Devise.mappings[:user]
    @user = user
    @user.confirm! # or set a confirmed_at inside the factory. Only necessary if you are using the confirmable module
    allow(controller).to receive(:current_user).and_return(@user)
    sign_in @user
  end

  def logged_user
    @user
  end

end

spec/support/database_cleaner.rb

spec/support/database_cleaner.rb

RSpec.configure do |config|

  config.before(:suite) do
    DatabaseCleaner.clean_with(:truncation)
    load "#{Rails.root}/db/seeds.rb"
  end

  config.before(:each) do
    DatabaseCleaner.strategy = :transaction
  end

  config.before(:each, :js => true) do
    DatabaseCleaner.strategy = :truncation
  end

  config.before(:each) do
    DatabaseCleaner.start
  end

  config.after(:each) do
    DatabaseCleaner.clean
  end

end

spec/controllers/subjects_controller_spec.rb

spec/controllers/subjects_controller_spec.rb

require 'spec_helper'

describe SubjectsController, :type => :controller do

  before(:each) do
    login create(:admin)
  end

  describe "GET index" do
    it "assigns all subjects as @subjects" do
      subject = create(:subject)
      get :index, {}
      expect(assigns(:subjects)).to include(subject)
    end
  end

  describe "GET show" do
    it "assigns the requested subject as @subject" do
      subject = create(:subject)
      get :show, {:id => subject.to_param}
      expect(assigns(:subject)).to eq(subject)
    end
  end

  describe "GET new" do
    it "assigns a new subject as @subject" do
      get :new, {}
      expect(assigns(:subject)).to be_a_new(Subject)
    end
  end

  describe "GET edit" do
    it "assigns the requested subject as @subject" do
      subject = create(:subject)
      get :edit, {:id => subject.to_param}
      expect(assigns(:subject)).to eq(subject)
    end
  end

  describe "POST create" do
    describe "with valid params" do
      it "creates a new Subject" do
        expect {
          post :create, {:subject => attributes_for(:subject) }
        }.to change(Subject, :count).by(1)
      end

      it "assigns a newly created subject as @subject" do
        post :create, { :subject => attributes_for(:subject) }
        expect(assigns(:subject)).to be_a(Subject)
        expect(assigns(:subject)).to be_persisted
      end

      it "redirects to the created subject" do
        post :create, {:subject => attributes_for(:subject) }
        expect(response).to redirect_to(subjects_path)
      end
    end

    describe "with invalid params" do
      it "assigns a newly created but unsaved subject as @subject" do
        allow_any_instance_of(Subject).to receive(:save).and_return(false)
        post :create, {:subject => {}}
        expect(assigns(:subject)).to be_a_new(Subject)
      end

      it "re-renders the 'new' template" do
        allow_any_instance_of(Subject).to receive(:save).and_return(false)
        post :create, { :subject => {} }
        expect(response).to render_template("new")
      end
    end
  end

  describe "PUT update" do
    describe "with valid params" do
      it "updates the requested subject" do
        @subject = create(:subject, name: "Alice")
        put :update, id: @subject, subject: attributes_for(:subject, name: "Bob")
        @subject.reload
        @subject.name.should eq("Bob")
      end

      it "assigns the requested subject as @subject" do
        @subject = create(:subject)
        put :update, {:id => @subject, :subject => attributes_for(:subject) }
        expect(assigns(:subject)).to eq(@subject)
      end

      it "redirects to the subject" do
        @subject = create(:subject)
        put :update, {:id => @subject, :subject => attributes_for(:subject) }
        expect(response).to redirect_to(edit_subject_path)
      end
    end

    describe "with invalid params" do
      it "assigns the subject as @subject" do
        @subject = create(:subject)
        allow_any_instance_of(Subject).to receive(:save).and_return(false)
        put :update, {:id => @subject, :subject => {}}
        expect(assigns(:subject)).to eq(@subject)
      end

      it "re-renders the 'edit' template" do
        @subject = create(:subject)
        allow_any_instance_of(Subject).to receive(:save).and_return(false)
        put :update, {:id => @subject, :subject => {}}
        expect(response).to render_template("edit")
      end
    end
  end

  describe "DELETE destroy" do
    it "destroys the requested subject" do
      subject = create(:subject)
      expect {
        delete :destroy, {:id => subject.id}
      }.to change(Subject, :count).by(-1)
    end

    it "redirects to the subjects list" do
      subject = create(:subject)
      delete :destroy, {:id => subject.id }
      expect(response).to redirect_to(subjects_url)
    end
  end

end

耙路线

             suggested_subjects GET    /suggested_subjects(.:format)                             suggested_subjects#index
         make_preferred_subject PUT    /subjects/:id/make_preferred(.:format)                    subjects#make_preferred
                       subjects GET    /subjects(.:format)                                       subjects#index
                                POST   /subjects(.:format)                                       subjects#create
                    new_subject GET    /subjects/new(.:format)                                   subjects#new
                   edit_subject GET    /subjects/:id/edit(.:format)                              subjects#edit
                        subject GET    /subjects/:id(.:format)                                   subjects#show
                                PUT    /subjects/:id(.:format)                                   subjects#update

app/controllers/subjects_controller.rb

app/controllers/subjects_controller.rb

class SubjectsController < ApplicationController

  load_and_authorize_resource

  def index
    @subjects = Subject.filter(params)

    respond_to do |format|
      format.html
      format.json { render json: {total: @subjects.count, subjects: @subjects}.to_json }
    end
  end
....
....
end

推荐答案

想通了.

ActionController::RoutingError 是另一个控制器规范调用的结果:

The ActionController::RoutingError was a result of another controller spec which was calling:

routes.draw 

此调用消除了后续规范的路由.目前的解决方案(感谢:

This call wiped out the routes for subsequent specs. The solution for now (thanks to:

http://pivotallabs.com/adding-routes-for-tests-specs-with-rails-3/ ) 添加:

after do

    # be sure to reload routes after the tests run, otherwise all your 
    # other controller specs will fail
    Rails.application.reload_routes!

end

也有帮助:

https://github.com/rspec/rspec-rails/issues/817

https://github.com/rspec/rspec-rails/issues/636

希望这会有所帮助并祝您好运!

Hope this helps and good luck!

这篇关于Rails 控制器 rspecs 因规范/控制器的 RoutingError 失败,但通过个别测试的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆