Help us understand the problem. What is going on with this article?

grapeで作成したAPIのconcernモジュールのRSpecを書く方法

More than 3 years have passed since last update.

概要

APIで共通の処理がある場合に、concernsディレクトリ以下のファイルに共通処理を書きDRYにしたい。
そのときにRSpecをどう書くかというお話です。
APIだけでなく、controllerの場合でも同様の方法が使えます。

方法

API(or controller)のconcernモジュールのテストで困るのは、エンドポイントをどうするかという点です。

方法としては、

  • モジュールをincludeしているAPIそれぞれにRSpecを書く
  • モジュールをincludeしているAPIのうち代表してひとつにのみRSpecを書く
  • 一般的なAPIをテストの時にのみ定義して、その一般的なAPIに対してRSpecを書く。

といったものがあるかと思いますが、今回は最後の方法を紹介します。

大まかに、以下の手順で行います。

  1. RSpecの中でfakeのAPI、エンドポイントを作成する
  2. fakeのAPIに当該モジュールをincludeする
  3. そのエンドポイントに対してリクエストを送りモジュールのテストをする

具体例

以下はinternalなAPIの認証のための処理で、正しいトークンを送っていない場合にBadRequestを発生させるモジュール。
このような処理はinternalなAPI全てで必要になるため、concerns以下に切り出している。

app/api/concerns/application_token_error_handler.rb
module ApplicationTokenErrorHandler
  extend ActiveSupport::Concern
  included do
    before do
      if params[:application_token] != Settings.application_token
        raise ActionController::BadRequest.new("Invalid application token #{params[:application_token]}")
      end
    end
  end
end

これに対するRSpecは以下のように書けます。
ポイントはRSpecの中で一般的なanonumousというエンドポイントを作成して、そこにリクエストを送るということです。

spec/requests/api/concerns/application_token_error_handler_spec.rb
require 'rails_helper'

describe ApplicationTokenErrorHandler, type: :request do
  before do
    # 1. fakeのAPIクラスとエンドポイントを定義
    class FakeApi < Grape::API
      # 2. テストしたいモジュールをincludeする
      include ApplicationTokenErrorHandler
      resources :anonymous do
        params do
          requires :application_token, type: String
        end
        get '/' do
          return status 200
        end
      end
    end

    # APIのルーティングを行うクラスにmountする(詳細は記事の範囲外なので省略)
    class API < Grape::API
      mount FakeApi
    end

    # 3. 上で定義したエンドポイントをリクエストする
    get '/anonymous', { application_token: application_token }
  end

  # テスト終了後に定義した定数を削除する
  after { Object.send :remove_const, :FakeApi }

  #
  # あとはいつも通りのAPIのテスト
  #

  # 正しいapplication_tokenをパラメタにしてリクエストした場合は200になる
  context 'application_token is right' do
    let(:application_token) { Settings.application_token }
    it { expect(response.status).to eq 200 }
  end

  # application_tokenが間違っている場合は400になる
  context 'application_token is mistaken' do
    let(:application_token) { 'invalid_token' }
    it { expect(response.status).to eq 400 }
  end
end

参考

grapeによるAPIの作成方法。
http://qiita.com/anoworl/items/756f01cc3d188ebad139

Controllerのconcernsモジュールをテストする例。
http://stackoverflow.com/questions/22055889/how-to-test-a-controller-concern-in-rails-4

finc
健康寿命を伸ばすアプリFiNCの開発・運営を行うモバイルヘルステクノロジーベンチャー
https://finc.com
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away