Question

J'écris rétroactivement certains tests, en utilisant RSpec, pour un projet Rails.

J'utilise la pierre précieuse CanCan fournir une autorisation. J'ai décidé d'écrire une spécification qui permettra de tester le modèle ability.rb. Je suis ensuite allé à tester mes autres modèles.

Je suis passé aux contrôleurs, et j'ai rencontré un énorme problème: je teste mes capacités tout recommencer

En fait, je dois bouchonner une série de modèles et stub leurs associations; sinon la réponse retourne juste 403 Forbidden.
La raison de cela, est que le contrôleur est essentiellement chargé de se soucier de l'autorisation.

Je ne suis pas tout à fait sûr où aller d'ici. J'écrasant jusqu'à 6 modèles, juste pour écrire un seul test. I sais le travail des capacités, qui est ce que ability_spec.rb est pour.

Donc, cette question est vraiment 2 fois:

  1. Dois-je me tester le modèle de capacité séparément?
  2. au cas où les tests de contrôleur sont concernés avec des autorisations appropriées?

Modifier     require 'spec_helper'     :: inclure TestHelpers # Concevoir pour donner votre accès spec aux aides

describe TokensController do
  before(:each) do
    @mock_user = User.new(:username => "bob", :email => "user@user.com", :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

Merci,
Robbie

Était-ce utile?

La solution

Je testons séparément le modèle cancan, mais l'essai ce qu'il permettra dans quelles conditions.

Je pense que si vous faites des choses comme

authorize! :take_over, @the_world

Alors je pense que vous devriez tester que dans le contrôleur. Je ne suis pas sûr que vous devez tester les 6 versions de vos modèles cependant.

Vous pouvez bouchonner le Ability.can? classe et l'ont répondu vrai / faux, et tester la façon dont vos poignées de contrôleur quand il peut (et surtout) quand il ne peut pas continuer.

Autres conseils

Je ne sais pas si cela est trop tard pour vous, mais je couru dans le même problème, et résolu à l'aide de l'exemple de code suivant -

before do
  @user = Factory.create(:user)
    sign_in @user

    @abilities = Ability.new(@user)
    Ability.stub(:new).and_return(@abilities)
  end
end

J'ai écrasa Capacité # nouveau, me donner une référence à l'instance de capacité qui contrôle l'utilisateur actuel. Ensuite, je peux bouchonner capacités spécifiques comme celle-ci:

@abilities.stub!(:can?).with(:destroy, regatta).and_return(true)

ou donner des privilèges d'administrateur:

@abilities.stub!(:can?).and_return(false)

Tout comme la réponse de Sam, mais à partir de la page wiki CanCan sur le test:

Test Controller

Si vous voulez la fonctionnalité d'autorisation d'essai au niveau du contrôleur une option consiste à vous identifier l'utilisateur qui dispose des autorisations appropriées.

user = User.create!(:admin => true) # I recommend a factory for this
# log in user however you like, alternatively stub `current_user` method
session[:user_id] = user.id 
get :index
assert_template :index # render the template since he should have access

Par ailleurs, si vous voulez tester le comportement du contrôleur indépendamment de ce qui est à l'intérieur de la classe de capacité, il est facile de stub la capacité avec un comportement que vous voulez.

def setup
  @ability = Object.new
  @ability.extend(CanCan::Ability)
  @controller.stubs(:current_ability).returns(@ability)
end

test "render index if have read ability on project" do
  @ability.can :read, Project
  get :index
  assert_template :index
end

Si vous disposez des autorisations très complexes, il peut conduire à de nombreuses possibilités de branchement. Si ceux-ci sont tous testés dans la couche de commande il peut conduire à des tests lents et gonflés. Au lieu de cela, je recommande de garder l'autorisation du contrôleur des tests de lumière et tester la fonctionnalité d'autorisation de manière plus approfondie dans le modèle de capacité grâce à des tests unitaires comme indiqué en haut.

Je pense que les besoins d'autorisation à faire principalement pour contrôleurs pour vous assurer que votre autorisation fonctionne correctement avec vos contrôleurs. Donc, pour le rendre DRY vous pouvez mettre en œuvre votre propre matcher être utilisé comme ceci

let!(:user) {create :user}
before { login_user_request user}

it "grants admin access to show action" do
  expect{ get :show, {id: user.id} }.to be_authorized
end
it "denies user access to edit action" do
  expect{ get :edit, {id: user.id} }.to be_un_authorized
end

puis mettre en œuvre ces matchers avec votre propre moyen de tester la façon dont une demande sera autorisée ou non

RSpec::Matchers.define :be_authorized do
  match do |block|
    block.call
    expect(response).to be_success
  end

  def supports_block_expectations?
    true
  end
end

RSpec::Matchers.define :be_un_authorized do
  match do |block|
    expect{
      block.call
    }.to raise_error(Pundit::NotAuthorizedError)
  end

  def supports_block_expectations?
    true
  end
end

Pourquoi ne pas inclure un

can :manage, :all do
  user.is_ultrasuper == 1
end

dans votre capacité et un param is_ultrasuper dans l'un de vos utilisateurs de fixation:

one: 
  id: 1 
  username: my_username 
  is_ultrasuper: 1

Ensuite, connectez-vous cet utilisateur lors de la configuration dans vos tests. Cela dans les tests, vous devriez être en mesure de faire quoi que ce soit du tout.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top