ruby-on-rails - 在使用 RSpec 测试 Controller 时模拟 CanCan 授权

标签 ruby-on-rails ruby testing rspec cancan

这是我要测试的 Controller :

class UsersController < ApplicationController
  load_and_authorize_resource

  def index
    @users = User.all

    respond_to do |format|
      format.html # index.html.erb
      format.json { render json: @users }
    end
  end

  def show
    @user = User.find(params[:id])

    respond_to do |format|
      format.html # show.html.erb
      format.json { render json: @user }
    end
  end

  #other actions here

end

如您所见,我使用了 CanCan 方法 load_and_authorize_resource,因此我为 RSpec 编写了一个 ControllerHelper:

# spec/support/controller_spec.rb
module ControllerHelper
  def should_authorize(action, subject)
    controller.should_receive(:authorize!).with(action, subject).and_return('passed!')
  end
end

然后我编写了 UserController 规范:

# spec/controllers/users_controller_spec.rb
require 'spec_helper'

describe UsersController do

  describe "GET #index" do
    before do
      @user = mock_model(User)
      should_authorize(:index, @user)
      User.stub!(:find).and_return(@user)
    end

    context "if the user passes all the authorizations" do
      it "populates an array of users" do
        User.should_receive(:find).and_return(@user)
        get :index
      end
      it "renders the :index view" do
        get :index
        response.should render_template :index
      end
    end
  end
end

但是我得到了这个错误

Failures:

1) UsersController GET #index if the user passes all the authorizations populates an array of users
       Failure/Error: get :index
         #<UsersController:0x000000037ee750> received :authorize! with unexpected arguments
            expected: (:index, #<User:0x1bf597c @name="User_1001">)
            got: (:index, User(id: integer, email: string, encrypted_password: string, reset_password_token: string, reset_password_sent_at: datetime, remember_created_at: datetime, sign_in_count: integer, current_sign_in_at: datetime, last_sign_in_at: datetime, current_sign_in_ip: string, last_sign_in_ip: string, created_at: datetime, updated_at: datetime, phone: string, address: string, city: string, cap: string, partitaiva: string, ragionesociale: string))
         # ./spec/controllers/users_controller_spec.rb:16:in `block (4 levels) in <top (required)>'

2) UsersController GET #index if the user passes all the authorizations renders the :index view
       Failure/Error: get :index
         #<UsersController:0x00000003802f98> received :authorize! with unexpected arguments
            expected: (:index, #<User:0x1bb0048 @name="User_1002">)
            got: (:index, User(id: integer, email: string, encrypted_password: string, reset_password_token: string, reset_password_sent_at: datetime, remember_created_at: datetime, sign_in_count: integer, current_sign_in_at: datetime, last_sign_in_at: datetime, current_sign_in_ip: string, last_sign_in_ip: string, created_at: datetime, updated_at: datetime, phone: string, address: string, city: string, cap: string, partitaiva: string, ragionesociale: string))
         # ./spec/controllers/users_controller_spec.rb:19:in `block (4 levels) in <top (required)>'

编辑

现在我的规范就是这样,而且有效!

# spec/controllers/users_controller_spec.rb
require 'spec_helper'

describe UsersController do

  describe "GET #index" do
    before do
      @user = mock_model(User)
      should_authorize(:index, User)
      User.stub!(:all).and_return(@user)
    end

    context "if the user passes all the authorizations" do
      it "populates an array of users" do
        User.should_receive(:all).and_return(@user)
        get :index
      end
      it "renders the :index view" do
        get :index
        response.should render_template :index
      end
    end
  end
end

谢谢,

恩里科

最佳答案

当您在 cancan 中使用 load_and_authorize_resource 时,它​​只会在操作为 updateshowedit< 时将用户实例传递给 authorize 方法destroy(我认为)。 当操作为 index 时,它改为传递 User 类。

这就是为什么您在 should_authorize 中的期望失败了

你可以在这里看到cancan是如何加载的:​​

https://github.com/ryanb/cancan/blob/master/lib/cancan/controller_resource.rb#L76

关于ruby-on-rails - 在使用 RSpec 测试 Controller 时模拟 CanCan 授权,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12750232/

相关文章:

php - PHPUnit 和 XDebug 可以一起工作吗?

ruby-on-rails - 使用 Moneris Canada 在活跃商家中定期计费

ruby-on-rails - 如何将所有选中的 check_box 值作为数组发布到 1 个字段?

ruby - Mechanize 带有后缀的选择 ID

ruby-on-rails - 迁移期间的 Ruby 工作流问题

java - 如何将参数值直接传递给TestNG、JUnit或其他框架方法?

ruby-on-rails - 模拟用户登录 Rspec - 使用 Faraday 和 Github-Api Gems

ruby-on-rails - 设计数据库迁移 - Ruby on Rails

mysql - Rails 应用程序中 mysql 查询性能缓慢

ruby - sinatra 应用程序不会在运行时启动