Question

Je suis nouveau sur Rspec et j'essaie d'entrer dans l'ensemble de l'état d'esprit BDD, donc je suis assez perplexe face à cette erreur.J'ai un moteur rails que j'essaie de tester.Voici le contrôleur de bulletin.Fondamentalement, avant toute action, je souhaite remplir la liste des cours.

class BulletinsController < ApplicationController
  before_filter :get_courses

  def new
    @bulletin = Bulletin.new(author_id: @user.id)
  end

 ...

 private
 def get_courses
   if @user.has_role? :admin
     @course_list = Course.all.sort_by(&:start_date)
   ...
   end
 end

Le contrôleur d'application dispose de certaines méthodes que je souhaite exécuter à chaque requête.J'utilise Devise dans l'application hôte, j'ai donc accès à la méthode current_user

class ApplicationController < ::ApplicationController
  before_filter :get_user
  ...
  def get_user
    @user = current_user
  end
  ...
end

Et voici la spécification que j'essaie d'exécuter :

describe BulletinsController do
  routes { MyEngine::Engine.routes }
  before { controller.stub(:authenticate_user!).and_return true }
  before { controller.stub(:get_user).and_return (@user = create(:user)) }

  describe "GET #new" do
    it "assigns a new bulletin to @bulletin" do
      bulletin = create(:bulletin)
      controller.stub(:get_courses)
      get :new
      assigns(:bulletin).should eq(bulletin)
    end
  end 
end

Lorsque j'essaie d'exécuter la spécification, j'obtiens l'erreur :

NoMethodError: undefined method 'id' for nil:NilClass

Je comprends que je reçois cela parce que @user n'est pas défini lorsqu'il est appelé dans la création du bulletin ;cependant, je pensais que le bloc before de la spécification définirait la variable @user après avoir supprimé le filtre :get_user.Lorsque je teste les usines dans la console, tout semble être créé avec les bonnes associations (bulletin -> auteur, bulletin -> cours, etc).

Je ne suis pas sûr de ce qui me manque quant à la raison pour laquelle la variable @user n'est pas transmise au code de mon contrôleur.Tout aperçu et/ou bon tutoriel pour rspec serait grandement apprécié.

Était-ce utile?

La solution

Je suppose que tu dois aussi faire un stub current_user et ce sera suffisant (pas besoin de stupéfier get_user):

before { controller.stub(:current_user).and_return (@user = create(:user)) }

Et je suppose que la bonne pratique est de laisser l'utilisateur (si vous en avez besoin plus d'une fois) :

routes { MyEngine::Engine.routes }
let!(:user) { create(:user) }
before { controller.stub(:current_user).and_return user }

Si vous avez besoin d'un accès aux méthodes privées, vous pouvez essayer quelque chose comme ceci :

subject.send(:current_user=, user)

Cela pourrait être un controller au lieu de subject, je ne sais pas quelle version est prise en charge.

Mise à jour.En fait, c'est vraiment délicat de tester des méthodes privées.j'ai vérifié ça current_user dans devise définit comme :

def current_#{mapping}
  @current_#{mapping} ||= warden.authenticate(scope: :#{mapping})
end

Alors, vous pouvez essayer le stub warden.authenticate aux retours user:

allow_any_instance_of(Warden).to receive(:authenticate).and_return(create(:user))

Autres conseils

Essayer d'encercler les méthodes que le concevoir pourrait utiliser sera assez difficile à moins que vous compreniez à quel point le développement fonctionne.

Le moyen recommandé de tester consiste simplement à vous connecter à l'utilisateur à l'aide de Devise Test Helper conformément à leur documentation: https://github.com/plataformatec/devise#test-HelPers

describe BulletinsController do
  routes { MyEngine::Engine.routes }
  before { sign_in(user) }

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

  describe "GET #new" do
    it "assigns a new bulletin to @bulletin" do
      bulletin = create(:bulletin)
      controller.stub(:get_courses)
      get :new
      assigns(:bulletin).should eq(bulletin)
    end
  end 
end

De cette façon, vous n'aurez pas à vous soucier de concevoir des méthodes et de l'emporter.Concentrez-vous simplement sur le test de votre propre méthode.:)

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