コントローラのテストでフィルタをスキップ

Yugui さんの「RSpecにおけるコンテキストをまたぐ共通部分」が面白いので私も Tips を。

コントローラにフィルタ*1をもりもり書いていくと、テストする場合に事前準備がすごくめんどくさくなる(ユーザ Foo でログインしてなきゃイケナイ、とかなんとか)んですが、その場合の Tips です。
spec_helperとか、そこから読み込む先に以下のように定義しておくと結構便利です。

module Spec:Runner
  class ExecutionContext
    module InstanceMethods
      def skip_filter(*filters)
        filters.each do |filter|
          controller.should_receive(filter).and_return(true)
        end
      end
    end
  end
end

使う場合は

context "the AdminController#list"
  setup
    skip_filter :admin_user_only, :login_required
    get :list
  end

  specify "assign[:users] should not be empty" do
    assign[:users].should_not be(:empty)
  end
end

のような感じで。メソッドによるフィルタチェーンにしか対応してませんが、ちょっといじればフィルタクラスを使う場合でもいけそうです。ダイナミックモッキンがあればこその書き方ですね。

もちろん、『フィルタ自身をテストしたい』という場合には skip してはだめです。その場合は context を別けるとか、そのフィルタ用のテストを書くとかすべきですね。

*1:特にアクセス制御系