Как я могу протестировать аутентифицированные API, созданные с использованием Rails 5? - PullRequest
0 голосов
/ 22 марта 2019

У меня есть API, который требует аутентификации, созданный с использованием Rails 5. Основной поток аутентификации состоит в том, что пользователь выполняет вход в систему с именем пользователя / паролем в кодированном Base64 заголовке Authorization: Basic вместе с ключом API. Затем он обменивается на токен авторизации, который записывается в таблицу базы данных пользователей и действует в течение некоторого периода времени. Последующие вызовы API требуют этот токен в заголовке Authorization: Bearer.

Проблема, с которой я столкнулся, заключается в том, что, когда я пытаюсь протестировать контроллер, требующий аутентификации, мне приходится проходить через этот танец регистрации пользователя (чтобы убедиться, что auth_token находится в тестовой базе данных таблица, так как это может быть первый тест, который выполняется, и т.д. ...) Это сложно, потому что, если, например, я тестирую контроллер с именем RecipesController, а моя аутентификация живет в AuthController, мне нужно переключить контроллеры, чтобы выполнить вход в систему.

Я успешно делал это в прошлом в spec_helper.rb, используя что-то вроде:

def login username, password
  current_controller = @controller
  ... setup login call ...

  post :login

  @controller = current_controller
  ... return auth token ...
end

Однако, как я понял в Почему параметры не передаются в моем тесте в Rails 5? , я считаю, что это портит мой тестовый запрос, и в результате параметры теряются.

Это похоже на довольно простой шаблон для использования, поэтому мне интересно, как это проверить? На самом деле я бы предпочел проверить аутентификацию отдельно и просто передать имитируемый пользовательский объект, но я не уверен, как это сделать, поскольку я не так знаком с Rails, как хотелось бы.

1 Ответ

1 голос
/ 22 марта 2019

Наличие вашей функции проверки подлинности в ApplicationController (при условии, что ваши рецепты унаследованы от этого)

def current_user
  return nil unless auth_token
  User.find(decoded_token['user_id'])
end

def authenticate_with_token
  head(:unauthorized) unless user_signed_in?
end

private

def user_signed_in?
  current_user.present?
end

def auth_token
  return nil unless request.headers['Authorization'].present?
  request.headers['Authorization']&.split(' ')&.last
end

def decoded_token
  JsonWebToken.decode(auth_token) #use your own decoder class
end

Затем вы можете добавить before_action :authenticate_with_token к действиям, для которых требуется аутентификация.

Для тестов вы можете добавить помощника для входа в систему пользователя, чтобы не повторять его во всех местах, где требуется авторизация.

module LoginSupport
  def login_user(user:, password:)
    valid_credentials =  { "email": user.email, password: password}
    post '/auth/sessions', params: valid_credentials

    valid_jwt_token = JSON.parse(response.body)["token"]
    { "Authorization": "Bearer #{valid_jwt_token}" }.merge(json_api_headers)
  end

  def json_api_headers
    {'Accept' => JSONAPI::MEDIA_TYPE, 'CONTENT_TYPE' => JSONAPI::MEDIA_TYPE}
  end
end

RSpec.configure do |config|
  config.include LoginSupport
end

Затем используйте возвращенный токен Auth в своем запросе в тестах RecipesContoller или в любом другом месте.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...