RSpecでshared_contextを使う

APIのrequest specを書く際、アクセストークンを生成してリクエストヘッダに埋め込んでおくというケースがよくある。そしてリソース単位でファイルを分けるていると、新しいリソースを追加する度に同じ定義をコピペする必要があって辛い。そんなときはshared_contextを使えば共通箇所を別ファイルに書き出せる。ということを覚えた。

  • spec/support/api_request_contexts.rb
shared_context 'user authenticated' do
  let(:application) do
    Doorkeeper::Application.create!(
      name:         'MyApp',
      redirect_uri: 'http://myapp.com/callback'
    )
  end

  let(:user) { FactoryGirl.create(:user) }

  let(:access_token) do
    Doorkeeper::AccessToken.create!(
      application_id:    application.id,
      resource_owner_id: user.id,
      scopes:            'public'
    )
  end

  let(:env) { { Authorization: "Bearer #{access_token.token}" } }
end

Railsの場合、shared_contextを定義したファイルをspec/support下に置くと、spec_helper.rbが勝手にrequireしてくれるので、include_contextでcontext名を指定するだけでよかった。

  • spec/requests/user_resource_spec.rb
require 'spec_helper'

describe 'User Resource' do

  include_context 'user authenticated'

  describe 'GET /api/v1/users' do
    it 'responds with 200 and return users' do
      get '/api/v1/users', {}, env
      expect(response.headers['Content-Type']).to eq 'application/json; charset=utf-8'
      expect(response).to be_success
      expect(response.status).to eq(200)
      expect(response.body).to be_json_as(
        meta: {
          total: Integer
        },
        users: Array
      )
    end
  end
end