Rails, authentification reposante & amp; RSpec - Comment tester de nouveaux modèles nécessitant une authentification

StackOverflow https://stackoverflow.com/questions/64827

Question

J'ai créé une application d'apprentissage utilisant Bort . , qui est une application de base incluant l’authentification reposante et RSpec. Je l'ai mis en marche et j'ai ajouté un nouvel objet qui nécessite que les utilisateurs soient connectés avant de pouvoir faire quoi que ce soit ( before_filter: login_required dans le contrôleur). [edit: Je devrais également mentionner que l'utilisateur has_many de la nouvelle classe et que seul l'utilisateur devrait pouvoir le voir.]

J'ai créé le nouveau modèle / contrôleur en utilisant les générateurs de Rspec qui ont créé un certain nombre de tests par défaut. Ils passent tous s’il n’ya pas de before_filter mais que plusieurs échouent, comme on pouvait s’y attendre, une fois que 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 a / n’est pas un utilisateur connecté? Ai-je besoin de tout un lot de correspondances non connectées - de tests de redirection? Je suppose que c’est une technique de moquage ou de montage, mais je suis novice en RSpec et un peu à la dérive. De bons liens au tutoriel RSpec seraient également appréciés.

Était-ce utile?

La solution

J'ai une configuration très similaire. Vous trouverez ci-dessous le code que j'utilise actuellement pour tester ce matériel. Dans chacun des décris , je mets:

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

Si vous avez uniquement besoin d'un identifiant 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é. De toute évidence, les méthodes d'assistance changent (très peu) à chaque tour, mais cela représente la plus grande partie du travail à votre place. 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

Autres conseils

Lorsque vous ne testez pas l'authentification mais les contrôleurs nécessitant l'authentification de l'utilisateur, je stub généralement la méthode de filtrage:

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

L'exemple ci-dessus fonctionne où mon before_filter est défini sur la méthode d'authentification:

before_filter :authenticate

et l'authentification dans mon application utilise l'authentification de base HTTP, mais il peut s'agir de 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 un moyen assez simple de tester.

J'ai trouvé quelques réponses à ma propre question. En gros, je devais comprendre comment simuler l'utilisateur de restful_authentication afin que les tests du contrôleur rspec générés automatiquement puissent réussir, même si j'avais ajouté before_filter: login_required . .

Voici quelques-unes de mes ressources récemment trouvées:

RSpec: ça devrait se comporter comme

rspec, restful_authentication, et login_required

utilisation de restful_authentication current_user dans les spécifications du contrôleur

SÉCHAGE de votre contrôleur CRUD RSpecs

Pour simuler un utilisateur connecté, je piraterai le contrôleur pour définir @ utilisateur_current 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
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top