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

孤街醉人 提交于 2019-12-03 15:37:08

问题


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", {}, { 'HTTP_AUTHORIZATION'=>"Token token=\"mytoken\"" }

But it is tedious to do that for each request.

I've tried setting request.env in the before block, but I get the no method NilClass error since request doesn't exist.

I need some way, maybe in the spec-helper, to globally get this header sent with all requests.


回答1:


I don't think you should depend on the header if you are not testing the header itself, you should stub the method that checks if the HTTP_AUTORIZATION is present and make it return true for all specs except the spec that tests that particular header

something like... on the controller

Controller...
  before_filter :require_http_autorization_token

  methods....

  protected
  def require_http_autorization_token
    something
  end

on the spec

before(:each) do
  controller.stub!(:require_http_autorization_token => true)
end

describe 'GET user' do
  it 'returns something' do
    #call the action without the auth token
  end

  it 'requires an http_autorization_token' do
    controller.unstub(:require_http_autorization_token)
    #test that the actions require that token
  end
end

that way one can forget the token and test what you really want to test




回答2:


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
    ...



回答3:


This is another way to do it if you are doing a post.

@authentication_params = { 'HTTP_AUTHORIZATION' => ActionController::HttpAuthentication::Token.encode_credentials(Temp::Application.config.api_key) }

expect { post "/api/interactions", @interaction_params, @authentication_params }.to change(Interaction, :count).by(1)

Note interaction_params is just a json object I am passing in.




回答4:


I know that this question has already been answered but here's my take on it. Something which worked for me:

request.headers['Authorization'] = token

instead of:

request.env['Authorization'] = token


来源:https://stackoverflow.com/questions/12761544/rspec-request-how-to-set-http-authorization-header-for-all-requests

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!