RSpec Request - как настроить HTTP-заголовок авторизации для всех запросов
Я использую запрос rspec для тестирования API JSON, для которого требуется api-ключ в заголовке каждого запроса.
Я знаю, что могу это сделать:
get "/v1/users/janedoe.json", {}, { 'HTTP_AUTHORIZATION'=>"Token token=\"mytoken\"" }
Но это утомительно делать это для каждого запроса.
Я попытался установить request.env
в предыдущем блоке, но я получаю no method NilClass error
, поскольку запрос не существует.
Мне нужно каким-то образом, возможно, в spec-helper
, чтобы глобально получить этот заголовок, отправленный со всеми запросами.
Ответы
Ответ 1
Я не думаю, что вы должны зависеть от заголовка, если вы не тестируете сам заголовок, вы должны заглушить метод, который проверяет наличие HTTP_AUTORIZATION и делает его возвратом true для всех спецификаций, кроме спецификации, которая проверяет этот конкретный заголовок
что-то вроде...
на контроллере
Controller...
before_filter :require_http_autorization_token
methods....
protected
def require_http_autorization_token
something
end
на 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
таким образом можно забыть токен и проверить, что вы действительно хотите проверить
Ответ 2
Чтобы установить его в верхний крючок, вам нужно получить к нему доступ, например
config.before(:each) do
controller.request.env['HTTP_AUTHORIZATION'] = ActionController::HttpAuthentication::Token.encode_credentials('mytoken')
end
Я тоже ненавидел гигантский хеш, но предпочитал быть явным в авторизации пользователя на разных этапах. В конце концов, это довольно критическая часть, и. Итак, я решил:
#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
то я могу использовать его так:
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
Я считаю, что это отлично подходит для тестирования разных уровней авторизации. В качестве альтернативы вы могли бы использовать вспомогательный метод для определения функции авторизации и получить тот же результат, например:
#spec/helpers/controller_spec_helpers.rb
module ControllerSpecHelpers
def authenticate
controller.stub(:authenticate! => true)
end
end
Однако для максимальной скорости и контроля вы можете комбинировать их
#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
а затем разрешить целые блоки с помощью
#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
Это еще один способ сделать это, если вы делаете сообщение.
@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)
Обратите внимание, что взаимодействие_парам - это просто объект json, который я передаю.
Ответ 4
Я знаю, что на этот вопрос уже был дан ответ, но здесь я беру на себя это. Что-то, что сработало для меня:
request.headers['Authorization'] = token
вместо:
request.env['Authorization'] = token