Frage

Ich bin neu bei Rspec und versuche, mich mit der gesamten BDD-Denkweise vertraut zu machen, daher bin ich über diesen Fehler ziemlich ratlos.Ich habe eine Rails-Engine, die ich testen möchte.Hier ist der Bulletin-Controller.Grundsätzlich möchte ich vor jeder Aktion die Liste der Kurse füllen.

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

Der Anwendungscontroller verfügt über einige Methoden, die ich bei jeder Anfrage ausführen möchte.Ich verwende „devise“ in der Host-App, sodass ich Zugriff auf die Methode „current_user“ habe

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

Und hier ist die Spezifikation, die ich ausführen möchte:

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

Wenn ich versuche, die Spezifikation auszuführen, erhalte ich die Fehlermeldung:

NoMethodError: undefined method 'id' for nil:NilClass

Ich verstehe, dass ich das bekomme, weil @user nicht definiert ist, wenn es im Bulletin-Building aufgerufen wird;Allerdings dachte ich, dass der Before-Block in der Spezifikation die @user-Variable definieren würde, nachdem der :get_user-Filter gelöscht wurde.Wenn ich die Fabriken in der Konsole teste, scheint alles mit den richtigen Zuordnungen erstellt zu sein (Bulletin -> Autor, Bulletin -> Kurs usw.).

Ich bin mir nicht sicher, was mir fehlt und warum die @user-Variable nicht in meinen Controller-Code übernommen wird.Für Einblicke und/oder gute Tutorials zu rspec wäre ich sehr dankbar.

War es hilfreich?

Lösung

Ich denke, Sie müssen auch stummeln current_user und es wird ausreichen (keine Notwendigkeit zu stummeln get_user):

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

Und ich denke, die gute Vorgehensweise besteht darin, dem Benutzer zu erlauben (wenn Sie ihn mehr als einmal benötigen):

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

Wenn Sie Zugriff auf private Methoden benötigen, können Sie Folgendes versuchen:

subject.send(:current_user=, user)

Könnte ein sein controller anstatt subject, nicht sicher, welche Version unterstützt wird.

Aktualisieren.Eigentlich ist es wirklich schwierig, private Methoden zu testen.Ich habe das überprüft current_user In devise definiert wie:

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

Sie können also Stub ausprobieren warden.authenticate zur Rückgabe user:

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

Andere Tipps

Versuch, die Methoden zu stumm herausstufen, die verwendet werden könnten, ist ziemlich schwierig, es sei denn, Sie verstehen, wie erarbeiten Arbeiten.

Der Empfehlungsweg, um zu testen, besteht darin, den Benutzer einfach mit einem Defise-Testhelfer gemäß deren Dokumentation anzumelden: https://github.com/plataFormatec/devise#Test-Helpers

generasacodicetagpre.

Auf diese Weise müssen Sie sich nicht darum kümmern, um Methoden zu entwickeln und zu stummeln.Fokussieren Sie einfach auf das Testen Ihrer eigenen Methode.:)

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top