views:

34

answers:

1

I'm retroactively writing some tests, using RSpec, for a Rails project.

I'm using the CanCan gem to provide authorization. I decided to write a spec that will test the ability.rb model. I then went on to test my remaining models.

I've moved on to controllers, and I've run into a huge snag: I'm testing my abilities all over again!

Basically, I have to stub out a series of models, and stub out their associations; otherwise the response just returns 403 Forbidden.
The reason for this, is that the controller is basically in charge of worrying about authorization.

I'm not quite sure where to go from here. I'm stubbing out up to 6 models, just to write a single test. I know the abilities work, that's what ability_spec.rb is for.

So this question is really 2-fold:

  1. Should I be testing the ability model separately?
  2. Should the controller tests be concerned with proper permissions?

Edit require 'spec_helper' include Devise::TestHelpers # to give your spec access to helpers

describe TokensController do
  before(:each) do
    @mock_user = User.new(:username => "bob", :email => "[email protected]", :password => "longpassword")
    @mock_user.role = "admin"
    sign_in @mock_user
    #Ability.stub!('can').and_return(true)
  end
  it "should let me see grids/:g_id/tokens index" do
    test_grid = mock_model(Grid)
    test_token = mock_model(Token)
    Grid.stub!(:find).and_return(test_grid)
    Token.stub!(:find).and_return(test_token)
    get 'index'

    a1 = Ability.new(@mock_user)
    a1.can?(:index, Token).should be_true # This line works fine; as it should
    puts response.status #This returns 403, which means CanCan::AccessDenied was raised
  end
end

Thanks,
Robbie

+1  A: 

I do test the cancan model separately, but testing what it will allow in what conditions.

I think if you are doing things like

authorize! :take_over, @the_world

Then I do think you should be testing that in the controller. I'm not sure you need to test ALL 6 versions of your models though.

You can stub out the Ability.can? class and have it respond true/false, and test how your controller handles when it can (and more importantly) when it cannot continue.

Jesse Wolgamott
Well I'm mostly doing load_and_authorize_resource, there are also some nested resources in there. The nested ones are the biggest pains to test.
Robbie
This is odd, I've added the test to my original question. "role => admin" has :manage, :all. Yet CanCan is throwing AccessDenied... I should add that manually visiting this page works just fine. Any ideas?
Robbie