在运行RSpec测试时绕过CanCan :: AccessDenied

时间:2015-08-01 13:21:10

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

我正在尝试为我的Restaurant模型运行一个强大的参数测试,并且遇到了一个阻碍开发进度的错误。在其控制器中,我使用CanCan方法load_and_authorize_resource只允许管理员创建,更新和销毁这些模型实例:

class RestaurantsController < ApplicationController
  load_and_authorize_resource param_method:  :restaurant_params, find_by: :slug
  ...
end

当涉及到运行测试时,我收到错误:

  1) RestaurantsController should permit POST #create to receive parameters :name
     Failure/Error: should permit(:name).
     CanCan::AccessDenied:
       You are not authorized to access this page.

是否有简单的方法可以绕过此授权?我在整个过程中都看了一遍,似乎没有一个明确的答案。

测试

describe RestaurantsController do
  let(:user) { FactoryGirl.create(:user, admin: true) }

  it { should permit(:name).for(:create) }
end

注意:我已经看过CanCan上的docs,他们说要创建一个admin属性设置为true的用户实例。即便如此,我仍然对如何在测试中插入此用户感到困惑。

2 个答案:

答案 0 :(得分:2)

经过一些研究后我得出结论,绕过这个问题的最佳方法更多地是通过Devise 登录我的User工厂而不是处理CanCanCan宝石本身。

根据您的设置,这可能会有所不同,但对于我的用户工厂,我的admin属性设置为true

<强> user.rb

FactoryGirl.define do
  factory :user do
    first_name "John"
    last_name "Doe"
    email "john@example.com"
    password "password"
    admin true
  end
end

然后我在名为spec的{​​{1}}文件夹中创建了一个子目录,并按照提供的Devise链接中的示例创建了用于登录用户的相应模块方法:

<强>规格/支持/ controller_macros.rb

support

然后在我的module ControllerMacros def login_admin before(:each) do @request.env["devise.mapping"] = Devise.mappings[:admin] sign_in FactoryGirl.create(:user) end end end 文件中,我只是扩展了这个模块,以便我可以使用rails_helper方法。 Devise示例 DID NOT 提到的是您需要login_admin此帮助程序中的require文件。某些人可能会理解这一点,但如果不小心,可能会被忽视:

<强>规格/ rails_helper.rb

controller_macros

最后,在您的控制器测试中,只需在需要的地方应用ENV['RAILS_ENV'] ||= 'test' require 'spec_helper' require File.expand_path('../../config/environment', __FILE__) require 'rspec/rails' require 'support/controller_macros' ActiveRecord::Migration.maintain_test_schema! RSpec.configure do |config| .... config.include Devise::TestHelpers, type: :controller config.extend ControllerMacros, type: :controller end 方法:

餐厅控制器测试

login_admin

答案 1 :(得分:2)

我用以下方式绕过了cancan的load_and_authorize_resource电话,因为我打算单独测试能力。

before { allow_any_instance_of(CanCan::ControllerResource).to receive(:load_and_authorize_resource){ nil } }