2017-10-20 54 views
1

je souffre pour le troisième jour, je ne comprends pas pourquoi je ne passe pas le test suivant:CanCan :: AccessDenied avec factory_girl et cancan, Comment écrire correctement l'usine?

4) Error: 
ArticlesControllerTest#test_should_get_index_if_admin: 
CanCan::AccessDenied: You are not authorized to access this page. 
    test/controllers/articles_controller_test.rb:22:in `block in <class:ArticlesControllerTest>' 

Qu'est-ce que je fais mal? aidez-moi s'il vous plaît!

J'ai une ancienne application (rails 4.2), avec de nombreuses données d'appareils.

Je tente de migrer mon environnement de test des appareils vers factory_girl. Donc je suis nouveau à ça.

Maintenant, je suis en utilisant:

  • cancancan + DEVISE
  • factory_girl + TestCase

Mon contrôleur articles:

class ArticlesController < ApplicationController 
    load_and_authorize_resource 
    before_filter :authenticate_user!, except: [:show] 

    def index 
    @articles = Article.paginate(page: params[:page], per_page: 10).includes(:translations) 
    end 
end 

Ability.rb:

Class Ability 
include CanCan::Ability 

def initialize(user) 
    user ||= User.new 

    # Everybody 
    can :show, [Article] 

    if user.admin? 
    can :manage, Article 
    end 
end 
end 

Mon article.rb usine est très simple:

FactoryGirl.define do 
factory :article do 
    content "MyText" 

    factory :one_article 
    factory :two_article 
end 
end 

Mon user.rb usine est tout aussi simple:

FactoryGirl.define do 
    factory :user do 
    sequence(:email) { |n| "user#{n}@mail.ru" } 
    password "password" 
    password_confirmation "password" 
    after(:create) {|u| u.roles_mask = 4} 
    profile 

    factory :valid_admin do 
     first_name "Administrator" 
     last_name "Administrator" 
     association :profile, factory: :admin_profile 
     after(:create) {|u| u.roles_mask = 2} 
    end 
    end 
end 

Mes articles test du contrôleur:

require 'test_helper' 

class ArticlesControllerTest < ActionController::TestCase 
    include Devise::Test::ControllerHelpers 

    setup do 
    @article = create(:one_article) 
    @admin = create(:valid_admin) 
    end 

    test 'should get index if admin' do 
    sign_in @admin 

    ability = Ability.new(@admin) 
    assert ability.can? :index, Article 

    get :index 
    assert_response :success 
    assert_not_nil assigns(:articles) 
    end 
end 

Infos par pry:

[1] pry(#<ArticlesControllerTest>)> sign_in @admin 
=> [[20709], "9BET5RWNuJPrGHUFi86d"] 
[2] pry(#<ArticlesControllerTest>)> ability = Ability.new(@admin) 
=> #<Ability:0x0000000c3c5ff8 
@rules= 
    [#<CanCan::Rule:0x0000000c3c5f80 
    @actions=[:show], 
    @base_behavior=true, 
    @block=nil, 
.............<<Many lines>> .............. 
[3] pry(#<ArticlesControllerTest>)> assert ability.can? :index, Article 
=> true 
[4] pry(#<ArticlesControllerTest>)> get :index 
CanCan::AccessDenied: You are not authorized to access this page. 
from /home/da/.rvm/gems/[email protected]/gems/cancancan-1.16.0/lib/cancan/ability.rb:217:in `authorize!' 

Merci d'avance pour votre aide!

+0

Si cela est une nouvelle utilisation de l'application 'de ActionDispatch :: IntegrationTest' au lieu d'un test du contrôleur. Aussi, j'utiliserais un test séparé pour tester votre classe de capacité en isolation au lieu de le faire ici. – max

+1

Je ne comprends vraiment pas ce que vous essayez de faire avec l'usine. J'utilise habituellement FactoryGirl avec ffaker pour générer des données aléatoires. Définir des usines comme 'factory: one_article' sent comme un luminaire. Les usines ne sont pas des appareils fixes.Ce sont des usines qui devraient créer des objets uniques. Si vous définissez en dur les valeurs de vos usines dans vos spécifications, vous vous trompez. Mauvais: 'expect (page) .to have_link (" Foo ")' Bien: 'expect (page) .to have_link (article.name)' – max

+0

Je ne comprenais vraiment pas le principe du test avec l'aide d'une tasse, maintenant Je suis devenu plus avancé dans ce domaine) merci pour votre conseil! J'ai enlevé la poubelle supplémentaire, refait certaines entités en trait, et ces erreurs ont disparu! – nilid

Répondre

1

Ce sont les lignes directrices de conception, vous devez créer une méthode pour vous connecter à l'utilisateur en tant qu'administrateur. Ceci est le login_method vous devez créer

tests de contrôleur (Test :: Unit)

Pour vous connecter en tant qu'administrateur pour un test donné, il suffit de faire:

class SomeControllerTest < ActionController::TestCase 
    # For Devise >= 4.1.1 
    include Devise::Test::ControllerHelpers 
    # Use the following instead if you are on Devise <= 4.1.0 
    # include Devise::TestHelpers 

    def setup 
    @request.env["devise.mapping"] = Devise.mappings[:admin] 
    sign_in FactoryGirl.create(:admin) 
    end 
end 

Remarque: Si vous utilisez le module confirmable, vous devez définir une date confirmée dans l'usine ou confirmer l'appel! avant sign_in.

Voici les bases pour préparer l'intérieur de votre usine:

FactoryGirl.define do 
    factory :account do 
    email { Faker::Internet.email } 
    password "password" 
    password_confirmation "password" 
    confirmed_at Date.today 
    end 
end 
+0

C'est une excellente réponse! – Sean

+0

@Sean Merci beaucoup –

+0

Merci pour votre réponse, mais je n'utilise pas rspec – nilid