doorkeeper-gem を使用している環境で、発行される AccessToken を Header に必要とする API アクセス (Request Spec) をテストするときの設定方法を備忘録として残します。
前提の環境
- Doorkeeper
- RSpec
- FactoryBot
コントローラとルーティング例はこんな感じ ※ 公式 Doc から少しいじってます
app/controllers/api/v1/credentials_controller.rb
class Api::V1::CredentialsController < Api::V1::ApiController
before_action :doorkeeper_authorize!
respond_to :json
# GET /api/v1/credential
def show
respond_with current_resource_owner
end
private
def current_resource_owner
User.find(doorkeeper_token.resource_owner_id) if doorkeeper_token
end
end
config/routes.rb
Rails.application.routes.draw do
use_doorkeeper
namespace :api do
namespace :v1 do
resource :credential, only: [:show]
end
end
end
Factory を用意
ディレクトリ構成
spec
└── factories
└── doorkeeper
├── access_grants.rb # 今回は使わない
├── access_tokens.rb
└── applications.rb
spec/factories/access_grants/applications.rb
FactoryBot.define do
factory :doorkeeper_application, class: 'Doorkeeper::Application' do
sequence(:name) { |n| "Application #{n}" }
redirect_uri { 'https://app.com/callback' }
end
end
spec/factories/access_grants/access_grants.rb
FactoryBot.define do
factory :doorkeeper_access_grant, class: 'Doorkeeper::AccessGrant' do
transient do
user { build :user }
end
association :application, factory: :doorkeeper_application
resource_owner_id { user.id }
redirect_uri { 'https://app.com/callback' }
expires_in { 100 }
scopes { 'read public' }
end
end
spec/factories/access_grants/access_tokens.rb
FactoryBot.define do
factory :doorkeeper_access_token, class: 'Doorkeeper::AccessToken' do
transient do
user { build :user }
end
association :application, factory: :doorkeeper_application
resource_owner_id { user.id }
expires_in { 2.hours }
scopes { 'read public' }
end
end
リクエストをテスト
Request Spec を書く
spec/requests/api/v0/credential_spec.rb
require 'rails_helper'
RSpec.describe 'Credential API', type: :request do
let(:user) { create :user }
let(:oauth_app) { create :doorkeeper_application }
let(:access_token) { create :doorkeeper_access_token, application: oauth_app, user: user, scopes: 'read' }
describe 'GET /api/v1/credential' do
context 'with authorized access' do
let(:headers) {{ 'Authorization': "Bearer #{access_token.token}" }}
before { get api_v1_credential_path(format: :json), headers: headers }
it 'responds with 200' do
expect(response).to have_http_status '200'
end
end
end
end
$ bundle exec rspec spec/requests/api/v1/credential_spec.rb
1 example, 0 failures
以上です。