Domanda

Sono nuovo a Rspec e sto cercando di entrare in tutta la mentalità BDD, quindi sono piuttosto scatenato di questo errore. Ho un motore dei binari che sto cercando di testare. Ecco il controller del bollettino. Fondamentalmente prima di qualsiasi azione che voglio popolare l'elenco dei corsi.

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
.

Il controller dell'applicazione ha alcuni metodi che voglio eseguire su ciascuna richiesta. Sto usando Devise nell'app Host in modo da avere accesso al metodo corrente_User

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

Ed ecco la specifica che sto cercando di eseguire:

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
.

Quando provo a eseguire le specifiche, ottengo l'errore:

NoMethodError: undefined method 'id' for nil:NilClass
.

Capisco che sto ottenendo questo perché @user non è definito quando viene chiamato nell'edificio del bollettino; Tuttavia pensavo che il blocco prima della specifica definirebbe la variabile @User dopo aver sfuggito il: Get_User Filter. Quando provo le fabbriche nella console, tutto sembra essere creato con le associazioni corrette (Bollettino -> Autore, Bollettino -> Corso, ecc.).

Non sono sicuro di cosa mi manca sul motivo per cui la variabile @user non viene trasportata al mio codice controller. Qualsiasi intuizione e / o buoni tutorial per RSPEC sarebbe molto apprezzata.

È stato utile?

Soluzione

Immagino che tu abbia anche bisogno di stub current_user e sarà sufficiente (non è necessario stub get_user):

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

E immagino che la buona pratica sia lasciare l'utente (se ne hai bisogno più di una volta):

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

Se hai bisogno di un accesso ai metodi privati, puoi provare qualcosa del genere:

subject.send(:current_user=, user)
.

Potrebbe essere un controller invece di subject, non è sicuro di quale versione supporta.

Aggiornamento.In realtà, è davvero difficile testare metodi privati.Ho controllato che current_user in devise definisce come:

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

Quindi, puoi provare a stub warden.authenticate per restituire user:

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

Altri suggerimenti

PROGETTO DI STUB OUT I metodi che si potrebbero usare potrebbero usare sarà abbastanza difficile a meno che tu non capisca come funziona il problema.

Il modo consigliabile per testare è semplicemente firmare all'utente utilizzando l'aiuto del test di Devise secondo la loro documentazione: 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
.

In questo modo, non dovrai preoccuparti di ideare i metodi e lo sfregandolo.Concentrati a testare il tuo metodo.:)

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top