1

私はcancanを使用したRailsアプリケーションを持っており、テストしているいくつかの異なる役割があります。私は、これらのテストを複数のコントローラーにまたがってセットアップするための最も乾燥した方法を探しています。

これは私がこれまでに持っているものの短縮版です。これを行うためのより良い方法はありますか?それでも私にはちょっと重い気がします。

describe OrganizationsController do
  render_views

  before do
    # User roles
    @unauthenticated = User.new
    @org_admin = Factory.create(:organization_admin)
    @org_staff = Factory.create(:org_staff)
    @customer = Factory.create(:customer)
    @admin = Factory.create(:admin)

    @organization = Factory.create(:organization)
    @org_for_admin = Factory.create(:organization, :user_group_id => @org_admin.user_group_id)
    @org_attr = FactoryGirl.attributes_for(:organization)
  end

  describe "GET 'show'" do
    authorized = %w(org_admin admin org_staff customer)
    not_authorized = %w(unauthenticated)

    not_authorized.each do |u|
      context "an organization by a user with role: #{u}" do
        before do
          user = instance_variable_get("@#{u}")
          get :show, :id => @organization.id, :format => 'json'
        end
        it { should_not respond_with :success }
        it { should respond_with :forbidden }
      end
    end

    authorized.each do |u|
      context "an organization by a user with role: #{u}" do
        before do
          user = instance_variable_get("@#{u}")
          get :show, :id => @organization.id, :format => 'json', :token => user.token
        end
        it { should respond_with :success }
        it { should render_template :show }
        it { should respond_with_content_type(/json/) }
        it { should assign_to(:organization).with_kind_of(Organization) }
      end
    end
  end

  describe "GET 'update'" do
    authorized = [%w(admin organization), %w(org_admin org_for_admin)]
    not_authorized = [%w(unauthenticated organization), %w(org_staff org_for_admin), %w(customer organization), %w(org_admin organization)]
    not_authorized.each do |u, o|
      context "an organization by a user with role: #{u}" do
        before do
          user = instance_variable_get("@#{u}")
          organization = instance_variable_get("@#{o}")
          put :update, :id => organization.id, :organization => @org_attr, :format => 'json'
        end
        it { should_not respond_with :success }
        it { should respond_with :forbidden }
      end
    end

    authorized.each do |u, o|
      context "an organization by a user with role: #{u}" do
        before do
          user = instance_variable_get("@#{u}")
          organization = instance_variable_get("@#{o}")          
          put :update, :id => organization.id, :organization => @org_attr, :format => 'json', :token => user.token
        end
        it { should respond_with :success }
        it { should render_template :update }
        it { should respond_with_content_type(/json/) }
        it { should assign_to(:organization).with_kind_of(Organization) }
      end
    end
  end
end

または、カンカンマッチャーを使用して、これらのタイプの能力テストをモデル仕様に移動し、各コントローラーアクションに対して成功したテストと禁止されたテストを行う必要がありますか?アンチパターン/文体の提案に関する私のテストに関する他のコメントも歓迎します。

ありがとう!

4

1 に答える 1

3

ウィキはあなたが感じている「問題点」を説明しています:

多くの場合、分岐の可能性が多いため、機能/統合レベルでユーザー権限を徹底的にテストすることは難しい場合があります。

.. Abilityクラス内にあるものとは別にコントローラーの動作をテストする場合は、任意の動作で能力を簡単にスタブ化できます。

def setup
  @ability = Object.new
  @ability.extend(CanCan::Ability)
  @controller.stubs(:current_ability).returns(@ability)
end

test "render index if have read ability on project" do
  @ability.can :read, Project
  get :index
  assert_template :index
end

良い質問。私はよくこれを自分で疑問に思いました。次回は、wikiの提案を試してみます。

于 2012-09-01T02:43:57.437 に答える