JohnDel
JohnDel

Reputation: 2102

Strange controller test behavior if cancan is enabled

I have an application with devise/cancan and a typical restful products controller with the following action:

def new
  @product = Product.new
end

In the products_controller_spec.rb I am testing it like this:

describe "GET 'new'" do
  it "returns http success" do
    Product.should_receive(:new)
    get 'new'
  end
end

If I run the test without cancan it works as expected and passes. If I add the cancan load_and_authorize_resource I am getting the following error:

Failure/Error: Product.should_receive(:new)
   (<Product(id: integer, tenant_id: integer, product_category_id: integer, tax_category_id: integer, brand_id: integer, name: string, description: string, order_quantity: decimal, size: decimal, decimal: decimal, items_per_unit: integer, created_at: datetime, updated_at: datetime) (class)>).new(any args)
       expected: 1 time
       received: 2 times

I have to bypass it by adding at_least(:one) in the end (so it looks like Product.should_receive(:new).at_least(:once) and it passes again).

Why is this happening? It has to do with cancan right? Why cancan is calling it twice and is there a better way to test it?

I am getting all kind of errors in controller tests when I am adding cancan and I've started wondering what cancan is doing and I have this strange behavior.

I have tested the abilities of a user and I have wrote many integration tests without a problem.

Last thing: I have a before block on top of the tests that I am signing in and giving the right role/permissions for accessing the controller like the following:

  let!(:tenant) { create(:tenant) }
  let!(:role)   { Role.where(name: "Admin", tenant_id: tenant.id).first }
  let!(:user)   { create(:user, role: role, tenant: tenant) }

  before do
    Tenant.current_id = tenant.id
    user.confirm!
    sign_in(user)
  end

Is there a way to bypass cancan (like calling skip_authorize_resource in some way in the test) because I want to test the controller method itself, not the abilities and the roles.

Upvotes: 0

Views: 70

Answers (1)

apneadiving
apneadiving

Reputation: 115531

When you use the load method of cancan, it does it for you automatically.

Change your action to:

def new
end

Upvotes: 1

Related Questions