rspec de prueba del controlador de error undefined method para nil:NilClass
-
20-12-2019 - |
Pregunta
Soy nuevo en el Rspec y estoy tratando de conseguir en el conjunto de la BDD mentalidad, así que estoy bastante perplejo acerca de este error.Me han rieles motor que estoy tratando de probar.Aquí está el boletín de controlador.Básicamente, antes de cualquier acción que desea rellenar la lista de cursos.
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
El controlador de aplicación tiene algunos métodos que quiero que se ejecute en cada solicitud.Yo estoy usando el de idear en la aplicación host para tener acceso a la current_user método
class ApplicationController < ::ApplicationController
before_filter :get_user
...
def get_user
@user = current_user
end
...
end
Y aquí está la especificación estoy tratando de ejecutar:
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
Cuando intento ejecutar la especificación, me sale el error:
NoMethodError: undefined method 'id' for nil:NilClass
Yo entiendo que yo estoy haciendo esto porque @usuario no está definido cuando es llamado en el boletín de la construcción;sin embargo, pensé que antes de bloque en la especificación se define la @variable de usuario después de golpear el :get_user filtro.Cuando hago la prueba de las fábricas en la consola, todo parece estar creado con las asociaciones adecuadas (boletín -> autor, boletín -> curso, etc).
No estoy seguro de lo que me estoy perdiendo de por qué el @variable de usuario no está siendo llevado a través de mi controlador de código.Conocimientos y/o buenos tutoriales para rspec sería muy apreciada.
Solución
Supongo que Usted también necesita a punta de current_user
y va a ser suficiente (no hay necesidad de punta de get_user
):
before { controller.stub(:current_user).and_return (@user = create(:user)) }
Y supongo que la buena práctica es permitir al usuario (si necesita más de una vez):
routes { MyEngine::Engine.routes }
let!(:user) { create(:user) }
before { controller.stub(:current_user).and_return user }
Si usted necesita un acceso a métodos privados, usted puede intentar algo como esto:
subject.send(:current_user=, user)
Podría ser un controller
en lugar de subject
, no está seguro de qué versión que soporta.
La actualización.En realidad, es muy complicado probar métodos privados.He comprobado que current_user
en devise
se define como:
def current_#{mapping}
@current_#{mapping} ||= warden.authenticate(scope: :#{mapping})
end
Así, se puede intentar punta de warden.authenticate
para las devoluciones user
:
allow_any_instance_of(Warden).to receive(:authenticate).and_return(create(:user))
Otros consejos
Tratando de resumir los métodos que el diseño podría estar usando será bastante difícil a menos que entienda cómo funciona los dispositivos.
La forma recomendada de probar es simplemente iniciar sesión en el usuario utilizando el ayudante de prueba de diseño según su documentación: 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 esta manera, no tendrá que preocuparse por diseñar métodos y derribarlo.Simplemente concéntrese en probar su propio método.:)