今回はちょいとマニアック。
問題
APIのテストはController Specではなく、Request Specに書くべきなのだが、DoorkeeperのサンプルコードはController Specで書かれている。こんな感じのコード
describe Api::V1::ProfilesController do describe 'GET #index' do let(:token) { double :accessible? => true } before do controller.stub(:doorkeeper_token) { token } end it 'responds with 200' do get :index, :format => :json response.status.should eq(200) end end end
何も気にせず、そのまま書くとRequest Specの中でcontrollerを呼んじゃっているので、ちゃんとスタブ化されずに401が返ってきてしまう。 てことでこのスタブを違う方法で利用して動作するようにしないといけない。
解決
指定したコントローラのインスタンスのスタブを作るようにする。
describe 'show user' do let(:path) { '/v1/users/' } it 'should show user' do user = FactoryGirl.create(:user, :valid_mail, :same_pass) token = double(accessible?: true, resource_owner_id: user._id.to_s) V1::UsersController.any_instance.stub(:doorkeeper_token) { token } get path res = JSON.parse(response.body) response.status.should eq(200) expect(res["item"]["email"]).to eq("test1@gmail.com") end end
ポイントはV1::UsersController.any_instance.stub(:doorkeeper_token)
の部分。ここでRequest SpecでもControllerをスタブ化することが出来るようになる。
users/show ではcurrent_user の情報を出すだけのコードになっている。 上記のテストはそのcurrent_user を直前でFactoryGirt.createしたものとしてちゃんと取って来れるかっていうテストになる。
ひとこと
FactoryGirl をちゃんとまともに使うようになったけど、これ便利ね。 ちなみに自分のRails API プロジェクトでは versionist ってgemも使ってる。これのジェネレータがなかなか良い。