読者です 読者をやめる 読者になる 読者になる

リア充爆発日記

You don't even know what ria-ju really is.

rspecのcontrollerのテストでログインチェックのテストを共通化したメモ

ログインがあるアプリだと、各コントローラでログインしている場合はこう!ログインしてない場合はこう!というテストが書きたくなる。
具体的なテストコードはこんな感じでござる。

describe FoosController do
  let(:user) { FactoryGirl.create(:user) }
  describe 'GET #new' do
    describe 'GET #new' do
    context 'by anonymous user' do
      before do
        get :new
      end
      it { is_expected.to redirect_to signin_path }
    end
    context 'by login user' do
      before do
        sign_in user
        get :new
      end
      it { is_expected.to render_template('new') }
    end
  end
end

これがいろんなところにできていたので、まとめたくなった。
要はgetとかのaction部分と、結果のテンプレートの種類あたりが可変にできればよいのだ。

こんなときの解決法の1つとしてshared exampleがある。

describe FoosController do
  let(:user) { FactoryGirl.create(:user) }
  describe 'GET #new' do
    it_should_behave_like 'authentication required' do
      let(:action){ get :new }
      let(:template) {'new'}
    end
  end
end

support/authentication_required.rb

require 'spec_helper'

shared_examples 'authentication required' do
  context 'by anonymous user' do
    before do
      action
    end
    it { is_expected.to redirect_to signin_path }
  end
  context 'by login user' do
    before do
      sign_in user
      action
    end
    it { is_expected.to render_template(template) }
  end
end

Rails4のconcernsなmoduleのテストをrspecで書く方法で書いたけど、shared_examplesをsupportの下に配置しているのは、ここだとspec実行時にロードされるから。

これでけっこうDRYになったね。