How do I simulate a login with RSpec?

前端 未结 4 1802
悲哀的现实
悲哀的现实 2020-12-08 02:27

I have been playing with Rails for a couple of years now and have produced a couple of passable apps that are in production. I\'ve always avoided doing any testing though an

相关标签:
4条回答
  • 2020-12-08 02:54

    The easiest way to login with a user on feature tests is to use the Warden's helper #login_as

    login_as some_user
    
    0 讨论(0)
  • 2020-12-08 03:04

    The answer depends on your authentication implementation. Normally, when a user logs in, you'll set a session variable to remember that user, something like session[:user_id]. Your controllers will check for a login in a before_filter and redirect if no such session variable exists. I assume you're already doing something like this.

    To get this working in your tests, you have to manually insert the user information into the session. Here's part of what we use at work:

    # spec/support/spec_test_helper.rb
    module SpecTestHelper   
      def login_admin
        login(:admin)
      end
    
      def login(user)
        user = User.where(:login => user.to_s).first if user.is_a?(Symbol)
        request.session[:user] = user.id
      end
    
      def current_user
        User.find(request.session[:user])
      end
    end
    
    # spec/spec_helper.rb
    RSpec.configure do |config|
      config.include SpecTestHelper, :type => :controller
    end
    

    Now in any of our controller examples, we can call login(some_user) to simulate logging in as that user.


    I should also mention that it looks like you're doing integration testing in this controller test. As a rule, your controller tests should only be simulating requests to individual controller actions, like:

    it 'should be successful' do
      get :index
      response.should be_success
    end
    

    This specifically tests a single controller action, which is what you want in a set of controller tests. Then you can use Capybara/Cucumber for end-to-end integration testing of forms, views, and controllers.

    0 讨论(0)
  • 2020-12-08 03:04

    As I couldn't make @Brandan's answer work, but based on it and on this post, I've came to this solution:

    # spec/support/rails_helper.rb
    Dir[Rails.root.join("spec/support/**/*.rb")].each { |f| require f } # Add this at top of file
    
    ...
    
    include ControllerMacros # Add at bottom of file
    

    And

    # spec/support/controller_macros.rb
    module ControllerMacros
    
      def login_as_admin
        admin = FactoryGirl.create(:user_admin)
        login_as(admin)
      end
    
      def login_as(user)
        request.session[:user_id] = user.id
      end
    
    end
    

    Then on your tests you can use:

    it "works" do
      login_as(FactoryGirl.create(:user))
      expect(request.session[:user_id]).not_to be_nil
    end
    
    0 讨论(0)
  • 2020-12-08 03:08

    Add helper file in spec/support/controller_helpers.rb and copy content below

    module ControllerHelpers
        def sign_in(user)
          if user.nil?
            allow(request.env['warden']).to receive(:authenticate!).and_throw(:warden, {:scope => :user})
            allow(controller).to receive(:current_user).and_return(nil)
          else
            allow(request.env['warden']).to receive(:authenticate!).and_return(user)
            allow(controller).to receive(:current_user).and_return(user)
          end
        end
      end
    

    Now add following lines in spec/rails_helper.rb or spec/spec_helper.rb file

    require 'support/controller_helpers'
    
    RSpec.configure do |config|
    
        config.include Devise::TestHelpers, :type => :controller
        config.include ControllerHelpers, :type => :controller
    
      end
    

    Now in your controller spec file.

    describe  "GET #index" do
    
        before :each do        
            @user=create(:user)
            sign_in @user
        end
          ...
    end
    

    Devise Official Link

    0 讨论(0)
提交回复
热议问题