Here is the Controller I want to test:
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
As you can see I use CanCan method load_and_authorize_resource
so I've written a ControllerHelper for RSpec:
# spec/support/controller_spec.rb
module ControllerHelper
def should_authorize(action, subject)
controller.should_receive(:authorize!).with(action, subject).and_return('passed!')
end
end
Then I've written the UserController Spec:
# 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
but I get this error
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)>'
EDIT
now my spec is like that, and it works!
# 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
Thanks,
enrico
When you're using load_and_authorize_resource in cancan, it only passes an instance of user to the authorize method when the action is
update
,show
,edit
ordestroy
(I think). When the action isindex
it passes the User class instead.That's why your expectation inside
should_authorize
failsYou can see how cancan does the loading here:
https://github.com/ryanb/cancan/blob/master/lib/cancan/controller_resource.rb#L76