访问root_path时出现RSpec InfiniteRedirectError

时间:2015-05-18 02:24:42

标签: ruby-on-rails ruby-on-rails-4 rspec capybara

这是一个水豚功能测试。我的控制器中没有为根页面设置的before_action过滤器,所以我完全被这个难过了。其他人有同样的问题吗?

导致错误的行只是

require 'rails_helper'

    def manually_create_user
        visit new_user_registration_path
        fill_in('user_first_name', :with => 'Test')
        fill_in('user_last_name', :with => 'User')
        fill_in('user_email', :with => 'testuser@email.com')
        fill_in('user_password', :with => 'testuser')
        fill_in('user_password_confirmation', :with => 'testuser')
        click_button('Sign up')
    end

    def create_user_and_login_as(type)
        user = FactoryGirl.create(type)
        visit(new_user_session_path)
        fill_in('user_email', :with => user.email)
        fill_in('user_password', :with => user.password)
        click_button('Log in')
    end


describe 'with users and roles' do  

    context "if user is not an admin" do

        it "makes sure Login/Logout works" do
            visit(root_path)
            click_link("Sign up")
            fill_in('user_email', :with => "testuser@email.com")
            fill_in('user_first_name', :with => "Test")
            fill_in('user_last_name', :with => "User")
            fill_in('user_password', :with => "password")
            fill_in('user_password_confirmation', :with => "password")
            click_button "Sign up"
            expect(current_path).to eq(root_path)
            expect(page).to have_content('Welcome! You have signed up successfully.')
        end
    end
end

非常奇怪。

此外,当单独运行此测试时,它会通过,但在运行整个测试套件时,它会因InfiniteRedirectError而失败。

user_and_role_spec.rb:

class StaticPagesController < ApplicationController
    before_action :an_admin?, only: [:admin]

  def home
    @testimonials = Testimonial.all
  end

  def admin
    @groups = Group.all

    @users = User.all

    @students = Student.all

    @teachers = Teacher.all
  end

  private

  def an_admin?
    unless signed_in? && (current_user.admin == true) 
      redirect_to root_path, notice: "You have to be a signed-in admin to view the admin page"
    end
  end

end

static_pages_controller.rb:

Rails.application.routes.draw do

  resources :materials

  root 'static_pages#home'

  devise_for :users, :controllers => { registrations: 'registrations' }

  get 'admin' => 'static_pages#admin'

  resources :groups
  resources :users
  resources :students
  resources :teachers
  resources :testimonials
  post 'assign_to_group' => 'students#assign_to_group' # Could have been 'patch', but default in the controller method is 'post', so I left the method as default and changed this route to 'post'. Doesn't NEED to be patch.
  post 'remove_from_group' => 'students#remove_from_group'
  post 'unassign_teacher' => 'groups#unassign_teacher'
  post 'assign_as_student' => 'teachers#assign_as_student'
  post 'assign_as_teacher' => 'students#assign_as_teacher'
  post 'add_student' => 'groups#add_student'
  post 'remove_student_from_group' => 'groups#remove_student_from_group'
end

routes.rb中:

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

require 'devise'

# Add additional requires below this line. Rails is not loaded until this point!

# Requires supporting ruby files with custom matchers and macros, etc, in
# spec/support/ and its subdirectories. Files matching `spec/**/*_spec.rb` are
# run as spec files by default. This means that files in spec/support that end
# in _spec.rb will both be required and run as specs, causing the specs to be
# run twice. It is recommended that you do not name files matching this glob to
# end with _spec.rb. You can configure this pattern with the --pattern
# option on the command line or in ~/.rspec, .rspec or `.rspec-local`.
#
# The following line is provided for convenience purposes. It has the downside
# of increasing the boot-up time by auto-requiring all files in the support
# directory. Alternatively, in the individual `*_spec.rb` files, manually
# require only the support files necessary.
#
# Dir[Rails.root.join('spec/support/**/*.rb')].each { |f| require f }

# Checks for pending migrations before tests are run.
# If you are not using ActiveRecord, you can remove this line.
ActiveRecord::Migration.maintain_test_schema!

RSpec.configure do |config|
  # 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 = true

  # RSpec Rails can automatically mix in different behaviours to your tests
  # based on their file location, for example enabling you to call `get` and
  # `post` in specs under `spec/controllers`.
  #
  # You can disable this behaviour by removing the line below, and instead
  # explicitly tag your specs with their type, e.g.:
  #
  #     RSpec.describe UsersController, :type => :controller do
  #       # ...
  #     end
  #
  # The different available types are documented in the features, such as in
  # https://relishapp.com/rspec/rspec-rails/docs
  config.infer_spec_type_from_file_location!

  config.include Devise::TestHelpers, :type => :controller

  Capybara.register_driver :rack_test do |app|
    Capybara::RackTest::Driver.new(app, :respect_data_method => true, :redirect_limit => 20)
  end

end

rails_helper.rb:

RSpec.configure do |config|
  # rspec-expectations config goes here. You can use an alternate
  # assertion/expectation library such as wrong or the stdlib/minitest
  # assertions if you prefer.
  config.expect_with :rspec do |expectations|
    # This option will default to `true` in RSpec 4. It makes the `description`
    # and `failure_message` of custom matchers include text for helper methods
    # defined using `chain`, e.g.:
    #     be_bigger_than(2).and_smaller_than(4).description
    #     # => "be bigger than 2 and smaller than 4"
    # ...rather than:
    #     # => "be bigger than 2"
    expectations.include_chain_clauses_in_custom_matcher_descriptions = true
  end

  # rspec-mocks config goes here. You can use an alternate test double
  # library (such as bogus or mocha) by changing the `mock_with` option here.
  config.mock_with :rspec do |mocks|
    # Prevents you from mocking or stubbing a method that does not exist on
    # a real object. This is generally recommended, and will default to
    # `true` in RSpec 4.
    mocks.verify_partial_doubles = true
  end
end

spec_helper.rb:

Started GET "/" for 127.0.0.1 at 2015-05-19 13:37:49 +0200
Processing by StaticPagesController#home as HTML
Redirected to http://www.example.com/
Filter chain halted as :an_admin? rendered or redirected
Completed 302 Found in 6ms (ActiveRecord: 0.0ms)
Started GET "/" for 127.0.0.1 at 2015-05-19 13:37:49 +0200
Processing by StaticPagesController#home as HTML
Redirected to http://www.example.com/
Filter chain halted as :an_admin? rendered or redirected
Completed 302 Found in 7ms (ActiveRecord: 0.0ms)
Started GET "/" for 127.0.0.1 at 2015-05-19 13:37:49 +0200
Processing by StaticPagesController#home as HTML
Redirected to http://www.example.com/
Filter chain halted as :an_admin? rendered or redirected

test.log中:

controller.class.skip_before_action :an_admin?

......等等

对我来说,这说明我的static_pages_controller中的before_action被踢了,但我不明白为什么会这样,给定an_admin?方法的代码?

更新:

我可能正在接近解决这个问题:在运行完整的测试套件时,在user_and_role_spec之前运行static_controller_spec。当我禁用static_controller_spec时,运行整个测试套件时,user_and_role_spec测试运行时没有错误。罪魁祸首似乎是这一行:

require "rails_helper.rb"

describe StaticPagesController do



describe "GET #home" do
        it "renders the :home view" do
            get :home
            expect(response).to render_template :home
        end
    end

    describe "GET #admin" do
        it "renders the :admin view" do
            # This is line 14. The next line is intended to disable the :an_admin? before_action in the controller
            controller.class.skip_before_action :an_admin?
            get :admin 
            expect(response).to render_template :admin
            # The next line is intended to reverse line 15
            controller.class.before_action :an_admin?
        end

        it "requires user to be signed_in"

        it "requires user to be an admin"
    end

end

这一行在static_controller_spec:

{{1}}

我想禁用此测试的before_action。说实话,我真的不明白那条线 - 它是从某个地方直接复制/粘贴。它似乎搞乱了我的user_and_role_spec测试,但我不明白为什么。有什么想法吗?

2 个答案:

答案 0 :(得分:0)

在您的user_and_role_spec.rb中,在结束结束end后您还有一个def create_user_and_login_as(type)。 您需要在规范底部有两个end才能关闭describe 'with users and roles' docontext "if user is not an admin" do

在您的routes.rb中,您需要在底部end关闭Rails.application.routes.draw do

我不确定您是否只是粘贴它们,但它在您的应用程序中确实很重要,并且当您发布代码时它确实很重要。

答案 1 :(得分:0)

解决:

参考我原来的帖子中的更新,我只是完全删除了static_pages_controller_spec中的那两个controller.class行,并且整个测试套件都通过了(感谢上帝!)。当然,它确实让我想知道为什么我首先在​​那里有那些线 - 我根本无法记住。

但是,这仍然有点神秘,这就是为什么我开始this other thread试图揭示它的原因。我知道我在这里要求相当多的手持,但任何帮助都会非常感激。我自己也做了很多学习,但也很高兴得到别人的意见。