RSpec Request - How to set http authorization header for all requests

后端 未结 4 2283
清歌不尽
清歌不尽 2021-02-07 06:01

I\'m using rspec request to test a JSON API that requires an api-key in the header of each request.

I know I can do this:

get \"/v1/users/janedoe.json\"         


        
4条回答
  •  刺人心
    刺人心 (楼主)
    2021-02-07 06:24

    To set it in a before hook you need to access it like

    config.before(:each) do
      controller.request.env['HTTP_AUTHORIZATION'] = ActionController::HttpAuthentication::Token.encode_credentials('mytoken')
    end
    

    I too hated the giant hash, but preferred to be explicit in authorizing the user in different steps. After all, it's a pretty critical portion, and . So my solution was:

    #spec/helpers/controller_spec_helpers.rb
    module ControllerSpecHelpers
      def authenticate user
        token = Token.where(user_id: user.id).first || Factory.create(:token, user_id: user.id)
        request.env['HTTP_AUTHORIZATION'] = ActionController::HttpAuthentication::Token.encode_credentials(token.hex)
      end
    end
    
    #spec/spec_helper.rb
    RSpec.configure do |config|
      ...
      config.include ControllerSpecHelpers, :type => :controller
    

    then I can use it like so

    describe Api::V1::Users, type: :controller do
      it 'retrieves the user' do
        user = create :user, name: "Jane Doe"
        authorize user
        get '/v1/users/janedoe.json'
      end
    end
    

    I find this great for testing different authorization levels. Alternatively, you could have the helper method spec out the authorize function and get the same result, like so

    #spec/helpers/controller_spec_helpers.rb
    module ControllerSpecHelpers
      def authenticate
        controller.stub(:authenticate! => true)
      end
    end
    

    However, for ultimate speed and control, you can combine them

    #spec/helpers/controller_spec_helpers.rb
    module ControllerSpecHelpers
      def authenticate user = nil
        if user
          token = Token.where(user_id: user.id).first || Factory.create(:token, user_id: user.id)
          request.env['HTTP_AUTHORIZATION'] = ActionController::HttpAuthentication::Token.encode_credentials(token.hex)
        else
          controller.stub(:authenticate! => true)
        end
      end
    end
    

    and then authorize entire blocks with

    #spec/spec_helper.rb
    ...
    RSpec.configure do |config|
      ...
      config.before(:each, auth: :skip) { authenticate }
    
    #**/*_spec.rb
    describe Api::V1::Users, type: :controller do
      context 'authorized', auth: :skip do
        ...
    

提交回复
热议问题