简体   繁体   English

这是使用RSpec和Shoulda测试用户角色的正确DRY方式吗?

[英]Is this the correct DRY way to test user roles with RSpec & Shoulda?

I have a rails application using cancan, and there are several different roles that I am testing. 我有一个使用cancan的rails应用程序,我正在测试几个不同的角色。 I'm looking for the most DRY way to setup these tests across several controllers. 我正在寻找在几个控制器上设置这些测试的最干的方法。

This is a shortened version of what I have so far. 这是我到目前为止的缩短版本。 Is there a better way to do this? 有一个更好的方法吗? It still feels kinda heavy to me. 它对我来说仍然有点沉重。

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

Or, should I be using the cancan matchers and move these types of ability tests into the model specs and just have a successful and a forbidden test for each controller action? 或者,我应该使用cancan匹配器并将这些类型的能力测试移动到模型规范中,并为每个控制器操作进行成功和禁止测试吗? Any other comments on my tests in terms of anti-patterns/stylistic suggestions are also welcome. 对于我的测试在反模式/风格建议方面的任何其他评论也是受欢迎的。

Thanks! 谢谢!

The wiki describes the "pain point" you're feeling: 维基描述了你感受到的“痛点”:

It can be difficult to thoroughly test user permissions at the functional/integration level because there are often many branching possibilities. 在功能/集成级别上彻底测试用户权限可能很困难,因为通常存在许多分支可能性。

.. if you want to test the controller behavior independently from what is inside the Ability class, it is easy to stub out the ability with any behavior you want. ..如果你想独立于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

Good question. 好问题。 I've often wondered this myself. 我自己经常想知道这件事。 Next time, I'm going to try the wiki's suggestion. 下一次,我将尝试维基的建议。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM