17

J'essaie de tester mon contrôleur et de maintenir la séparation des préoccupations.RSpec dans Rails: comment ignorer un before_filter?

La première préoccupation est "Qui est capable d'exécuter quelle action?" J'utilise authlogic pour l'authentification et be9's acl9 pour l'autorisation. Mais cela ne devrait pas importer, toutes mes préoccupations d'autorisation sont traitées dans un before_filter. Je teste un tel before_filter par quelque chose de similaire à ceci:

describe SomeModelsController, "GET to index (authorization)" do 
    before(:each) do 
    @siteadmin = mock_model(User) 
    @siteadmin.stub!(:has_role?).with("siteadmin", nil).and_return(true) 
    end 

    it "should grant access to a siteadmin" do 
    controller.should_receive(:current_user).at_least(:once).and_return(@siteadmin) 
    get :index 
    response.should be_success 
    end 
end 

Cette spécification fonctionne très bien! Maintenant, la deuxième préoccupation est "Est-ce que l'action fait ce qu'elle est censée faire?"
Ceci n'implique pas de vérifier l'autorisation. La meilleure/solution la plus propre serait que sauter before_filter tous ensemble et juste faire quelque chose comme:

describe SomeModelsController, "GET to index (functional)" do 
    it "should find all Models" do 
    Model.should_receive(:find).with(:all) 
    end 
end 

Sans avoir à se soucier quel utilisateur avec le rôle de Wich doit d'abord connecté. En ce moment, je l'ai résolu comme ça:

describe SomeModelsController, "GET to index (functional)" do 
    before(:each) do 
    @siteadmin = mock_model(User) 
    @siteadmin.stub!(:has_role?).with("siteadmin", nil).and_return(true) 
    controller.stub!(:current_user).and_return(@siteadmin) 
    end 

    it "should find all Models" do 
    Model.should_receive(:find).with(:all) 
    end 
end 

Si je décidé que mon siteadmin n'a pas le droit d'accéder à l'action d'index plus, il ne serait pas seulement casser une spécification - à savoir la spécification qui doit briser en un tel cas - mais aussi la seconde spécification totalement indépendante.

Je sais que c'est fondamentalement un problème mineur, mais ce serait bien si quelqu'un pouvait trouver une solution (élégante)!

Répondre

34

Pour sauter le filtre avant:

controller.class.skip_before_filter :name_of_method_used_as_before_filter 

L'une mise en garde (mentioned the docs) est que cela ne fonctionne que pour les filtres méthode référence, non procs.

Sinon, vous pouvez stub current_user.has_role?

describe SomeModelsController, "GET to index (functional)" do 
    before(:each) do 
    controller.current_user.stub!(:has_role?).and_return(true) 
    end 

    it "should find all Models" do 
    Model.should_receive(:find).with(:all) 
    end 
end 
+0

Merci, n'a pas pensé à celui-ci. S'il n'y a pas moyen d'ignorer le before_filter, cela pourrait être la meilleure solution. – sebastiangeiger

+0

Ok, j'ai mis à jour ma réponse. J'espère que c'est ce dont vous avez besoin. – Baldu

+0

Nice, sauter le filtre avant fonctionne. Le seul inconvénient est que acl9 installe un filtre lambda sans nom par défaut, donc je dois forcer la création d'un before_filter nommé. – sebastiangeiger

-9

Que diriez-vous de faire tout simplement pas une requête GET? Essayez d'appeler la méthode du contrôleur par elle-même.

controller.index 
0

Question ancienne, mais j'ai dû résoudre ce problème récemment. Cela ne fonctionnera que pour Rails 3.1, pour les versions précédentes, vous devez remplacer _process_action_callbacks avec filter_chain (non testé)

Vous pouvez simplement supprimer un Proc correspondant de la chaîne de filtre comme si (Test :: Exemple unitaire):

class RandomControllerTest < ActionController::TestCase 
    def setup 
    @controller.class._process_action_callbacks.each do |f| 
     @controller.class._process_action_callbacks.delete(f) if f.raw_filter.to_s.match(/**<match for your proc>**/) 
    end 
    end 
end 
Questions connexes