2008-09-15 5 views
17

J'ai créé une application d'apprentissage en utilisant Bort, qui est une application de base qui inclut Restful Authentication et RSpec. Je l'ai mis en marche et ai ajouté un nouvel objet qui exige que les utilisateurs soient connectés avant qu'ils puissent faire n'importe quoi (before_filter :login_required dans le contrôleur). [edit: Je devrais également mentionner que l'utilisateur has_many de la nouvelle classe et seulement l'utilisateur devrait être capable de le voir.]Rails, Authentification Restful & RSpec - Comment tester les nouveaux modèles qui nécessitent une authentification

J'ai créé le nouveau modèle/contrôleur en utilisant les générateurs de Rspec qui ont créé un certain nombre de défaut tests. Ils passent tous s'il n'y a pas before_filter mais plusieurs échouent, comme il se doit, une fois que le before_filter est en place.

Comment puis-je faire en sorte que les tests générés s'exécutent comme s'il y avait ou non un utilisateur connecté? Ai-je besoin de tout un lot de correspondance non connecté - des tests de redirection? Je suppose que c'est une sorte de technique de moquerie ou de fixation, mais je suis nouveau à RSpec et un peu à la dérive. De bons liens tutoriels RSpec seraient également appréciés.

Répondre

7

J'ai une configuration très similaire, et ci-dessous est le code que j'utilise actuellement pour tester ce genre de choses. Dans chacun des describe s je mets:

it_should_behave_like "login-required object" 
def attempt_access; do_post; end 

Si tout ce que vous avez besoin est une connexion, ou

it_should_behave_like "ownership-required object" 
def login_as_object_owner; login_as @product.user; end 
def attempt_access; do_put; end 
def successful_ownership_access 
    response.should redirect_to(product_url(@product)) 
end 

Si vous avez besoin de propriété. Évidemment, les méthodes d'aide changent (très peu) à chaque tour, mais cela fait la plupart du travail pour vous. Ceci est dans mon spec_helper.rb

shared_examples_for "login-required object" do 
    it "should not be able to access this without logging in" do 
    attempt_access 

    response.should_not be_success 
    respond_to do |format| 
     format.html { redirect_to(login_url) } 
     format.xml { response.status_code.should == 401 } 
    end 
    end 
end 

shared_examples_for "ownership-required object" do 
    it_should_behave_like "login-required object" 

    it "should not be able to access this without owning it" do 
    attempt_access 

    response.should_not be_success 
    respond_to do |format| 
     format.html { response.should be_redirect } 
     format.xml { response.status_code.should == 401 } 
    end 
    end 

    it "should be able to access this if you own it" do 
    login_as_object_owner 
    attempt_access 

    if respond_to?(:successful_ownership_access) 
     successful_ownership_access 
    else 
     response.should be_success 
    end 
    end 
end 
4

J'ai trouvé quelques réponses à ma propre question. Fondamentalement, je devais comprendre comment mocker l'utilisateur de restful_authentication de sorte que les tests de contrôleur rspec autogénérés pourraient passer même si j'avais ajouté before_filter: login_required.

Voici quelques-unes de mes ressources nouvellement trouvées:

RSpec: It Should Behave Like

rspec, restful_authentication, and login_required

using restful_authentication current_user inside controller specs

DRYing up your CRUD controller RSpecs

1

Pour se moquer d'un utilisateur étant connecté, je pirater le contrôleur pour définir @current_user manuellement:

module AuthHelper 
    protected 

    def login_as(model, id_or_attributes = {}) 
    attributes = id_or_attributes.is_a?(Fixnum) ? {:id => id} : id_or_attributes 
    @current_user = stub_model(model, attributes) 
    target = controller rescue template 
    target.instance_variable_set '@current_user', @current_user 

    if block_given? 
     yield 
     target.instance_variable_set '@current_user', nil 
    end 
    return @current_user 
    end 

    def login_as_user(id_or_attributes = {}, &block) 
    login_as(User, id_or_attributes, &block) 
    end 
end 
7

Lorsqu'ils ne sont pas tester l'authentification mais le test des contrôleurs qui a besoin de l'utilisateur à authentifier je Stub habituellement la méthode du filtre:

before(:each) do 
    controller.stub!(:authenticate).and_return(true) 
end 

L'exemple ci-dessus fonctionne où mon before_filter est réglé sur la méthode authenticate :

before_filter :authenticate 

et Authentifier dans mon application utilise l'authentification HTTP de base, mais il peut vraiment être tout autre mécanisme d'authentification.

private 
def authenticate 
    authenticate_or_request_with_http_basic do |user,password| 
    user == USER_NAME && password == PASSWORD 
    end 
end 

Je pense que c'est une façon assez simple de tester.

+0

Le plus doux! – AnkitG

Questions connexes