如果启用了cancan,则会出现奇怪的控制器测试行为

时间:2013-05-31 07:58:19

标签: ruby-on-rails unit-testing rspec cancan

我有一个带有devise / cancan的应用程序和一个典型的restful产品控制器,其操作如下:

def new
  @product = Product.new
end

products_controller_spec.rb我正在测试它:

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

如果我在没有cancan的情况下运行测试,它会按预期工作并通过。如果我添加了cancan load_and_authorize_resource,我收到以下错误:

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

我必须通过最后添加at_least(:one)来绕过它(所以它看起来像Product.should_receive(:new).at_least(:once)并再次传递)。

为什么会这样?它与cancan有关吗?为什么cancan会调用它两次并且有更好的方法来测试它?

当我添加cancan时,我在控制器测试中遇到了各种错误,我开始想知道cancan正在做什么,我有这种奇怪的行为。

我已经测试了用户的能力,并且我已经编写了许多集成测试而没有任何问题。

最后一件事:我在登录的测试之上有一个前块,并为访问控制器提供了正确的角色/权限,如下所示:

  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

有没有办法绕过cancan(比如在测试中以某种方式调用skip_authorize_resource),因为我想测试控制器方法本身,而不是能力和角色。

1 个答案:

答案 0 :(得分:1)

当您使用cancan的load方法时,它会自动为您完成。

将您的操作更改为:

def new
end