在使用RSpec测试控制器时模拟CanCan授权

这是我要测试的控制器:

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 # received :authorize! with unexpected arguments expected: (:index, #) 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 ' 2) UsersController GET #index if the user passes all the authorizations renders the :index view Failure/Error: get :index # received :authorize! with unexpected arguments expected: (:index, #) 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 ' 

编辑

现在我的规格是这样的,它的确有效!

 # 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时,它只会在操作updateshoweditdestroy (我认为)时将用户实例传递给authorize方法。 当操作是index它会传递User类。

这就是为什么你在should_authorize里面的should_authorize失败了

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

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