【问题标题】:How to test cancancan abilities in controller test with default testing framework (minitest)如何使用默认测试框架(minitest)在控制器测试中测试 cancancan 能力
【发布时间】:2015-12-27 21:20:47
【问题描述】:

在我的 Rails 应用程序中,我有两个用户角色:“学生”和“管理员”。他们对不同页面有不同的访问权限,例如,“admin”可以访问列表用户页面(索引),但“student”不能。这是使用cancancan 控制的。

现在我正在为控制器编写测试,因为我有两个不同的角色,(据我所知)我需要对一个行为进行两个单独的测试,例如:

test "should get index for admin" do
    sign_in(users(:admin))
    get "index"
    assert_response :success
end

test "should not get index for student" do
    sign_in(users(:student))
    get "index"
    assert_response :unauthorized
end

sign_in(*) 是处理用户登录(会话等)的方法

由于我正在考虑添加更多角色(例如“经理”、“代理”),因此每次添加角色时都需要为所有控制器方法添加新测试。这很乏味而不是“干”,所以我试图找到一种更优雅的方式来处理这个问题。这是我的第一个想法:

在我的 test_helper.rb 中,我添加了:

def assert_admin_only(&block)
    sign_in(users(:admin))
    instance_exec(&block)
    assert_response :success
    sign_out

    sign_in(users(:student))
    instance_exec(&block)
    assert_response :unauthorized
    sign_out

    sign_in(users(:agent))
    instance_exec(&block)
    assert_response :unauthorized
    sign_out
end

然后在我的测试中:

test "should get index for admin only" do
    assert_admin_only do
        get "index"
    end
end

所以每次我添加一个新角色时,我只需要在 test_helper.rb 方法中添加几行来测试能力。

但是,它并没有像我想象的那样工作,因为“功能测试允许您测试每个测试方法的单个控制器操作。”根据Rails API DOC,在我的代码中,我触发了两个甚至更多的动作。出于某种原因,我无法弄清楚,似乎sign_insign_out 实际上并没有改变 current_user (尽管它们在实际请求中工作得很好),这基本上使我的尝试失败了。

总之,我想为不同的用户角色重复使用我的测试,这样我就不必在每次添加新角色时都浪费时间复制和粘贴现有代码。如果你们能提供一些绝妙的想法,我将不胜感激。

【问题讨论】:

    标签: ruby-on-rails unit-testing minitest cancancan


    【解决方案1】:

    例如:

    require 'test_helper'
    
    class ArticlesControllerTest < ActionController::TestCase
      include Devise::TestHelpers
    
      setup do
        @article = articles(:one)
        @admin = users(:admin)
        @expert = users(:expert)
        @user = users(:emelya)
        @student = users(:student)
      end
    
      test "should get index if admin" do
        sign_in @admin
        ability = Ability.new(@admin)
        assert ability.can? :index, Article
    
        get :index
        assert_response :success
        assert_not_nil assigns(:articles)
      end
    
    
      test "should not get index for other users" do
        [@expert, @user, @student] do |user|
          sign_in user
          ability = Ability.new(user)
          assert ability.cannot? :index, Article
    
          assert_raise CanCan::AccessDenied do
            get :index
          end
    
          sign_out user
        end
      end
    
    end
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-06-26
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多