这是使用RSpec& amp;测试用户角色的正确DRY方式吗?早该?

时间:2012-08-22 20:25:18

标签: ruby-on-rails rspec cancan shoulda

我有一个使用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

或者,我是否应该使用cancan匹配器并将这些类型的能力测试移动到模型规范中,并且只为每个控制器操作进行成功和禁止测试?对于我的测试在反模式/风格建议方面的任何其他评论也是受欢迎的。

谢谢!

1 个答案:

答案 0 :(得分:3)

wiki描述了你感受到的“痛点”:

  

要彻底测试用户权限可能很困难   功能/集成级别,因为通常有很多分支   可能性。

     

..如果要测试控制器行为   独立于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

好问题。我自己经常想知道这件事。下一次,我将尝试维基的建议。