ruby on rails 4 - rails - "Método indefinido ''env'' para nil: NilClass" en el error ''setup_controller_for_warden'' al probar el dispositivo con Rspec
factory bot rails (10)
Aparentemente hay problemas con Devise::TestHelpers
y pruebas de integración, por lo que tal vez ese sea el problema aquí.
https://github.com/plataformatec/devise (mencionado en README, Issues, etc., también vea preguntas relacionadas con SO):
Estos ayudantes no van a funcionar para pruebas de integración impulsadas por Capybara o Webrat. Están destinados a ser utilizados solo con pruebas funcionales. En su lugar, complete el formulario o configure explícitamente al usuario en sesión;
Intento crear una especificación para un flujo de cierre utilizando factorygirl para crear un usuario y luego usar el método sign_in
de Devise para autenticar al usuario, luego usar capybara para hacer clic en el enlace " sign_in
sesión".
Estoy obteniendo (lo que me parece que es) un extraño error cuando ejecuto la especificación:
Failures:
1) Sign out flow successfully redirects to the welcome index (root)
Failure/Error: Unable to find matching line from backtrace
NoMethodError:
undefined method `env'' for nil:NilClass
# /home/vagrant/.rvm/gems/ruby-2.0.0-p576/gems/devise-3.4.1/lib/devise/test_helpers.rb:24:in `setup_controller_for_warden''
Finished in 0.00226 seconds (files took 3.32 seconds to load)
1 example, 1 failure
Aquí está la especificación:
require ''rails_helper''
describe "Sign out flow" do
include Devise::TestHelpers
describe "successfully" do
it "redirects to the welcome index (root)" do
user = create(:user)
sign_in user
within ''.user-info'' do
click_link ''Sign Out''
end
expect(current_path).to eq root_path
end
end
end
Y mi fábrica user.rb
:
FactoryGirl.define do
factory :user do
name "Fake User"
sequence(:email, 100) { |n| "person#{n}@example.com" }
password "helloworld"
password_confirmation "helloworld"
confirmed_at Time.now
end
end
Parece que el error se desencadena simplemente desde la línea que include Devise::TestHelpers
, ya que he intentado comentar todo el contenido de la especificación y aún así obtener el mismo error.
Pensé que los ayudantes de prueba de Devise funcionarían de la caja; perdí alguna configuración? Gracias.
Aquí está mi solución:
class ActiveSupport::TestCase
# all the normal stuff
end
class ActionController::TestCase
include Devise::TestHelpers
end
Como ya han dicho otros, está incluyendo el Devise::TestHelpers
. Eso es para probar los controladores . Si aún desea iniciar sesión automáticamente en un usuario de prueba en sus pruebas de integración, consulte las Instrucciones oficiales para el uso de Capybara .
Usando Devise con Capybara
Básicamente, lo que tienes que hacer es primero habilitar el modo de prueba de Warden:
include Warden::Test::Helpers
Warden.test_mode!
Luego, (cree y) inicie sesión con su usuario:
user = FactoryGirl.create(:user)
login_as(user, scope: :user)
Ejemplo:
# spec/features/survey_spec.rb
require ''rails_helper''
feature ''survey app'' do
include Warden::Test::Helpers
let(:user) { create(:user) }
let(:survey) { create(:survey_with_questions) }
before do
# Sign the User in
Warden.test_mode!
login_as(user, scope: user)
end
it ''renders the survey'' do
visit survey_show_path(survey)
expect(page).to have_content(survey.title)
end
end
En Rails 5 debe incluir Devise::Test::IntegrationHelpers
lugar Devise::Test::ControllerHelpers
:
# rails_helper.rb
config.include Devise::Test::IntegrationHelpers, type: :feature
Ver más:
Estaba teniendo este problema al intentar sign_in
un usuario en un sign_in
anterior:
before(:context) do
create(:skill, name: ''Google Maps API''.downcase)
user = create(:user)
sign_in user
end
Colocar sign_in
dentro del gancho anterior conduce a:
Failure/Error: sign_in user
NoMethodError:
undefined method `env'' for nil:NilClass
Pero colocarlo dentro de un ejemplo funciona bien:
shared_examples_for(''an authenticated resource.'') do
describe ''An authenticated request'' do
it "responds with HTTP status OK" do
user = create(:user)
sign_in user
make_request
expect(response).to have_http_status(:ok)
end
end
end
Pero esto se puede mejorar, colocando el signo_in en un antes (: ejemplo) que también funcionará:
context ''allow search by keyword'' do
let!(:skill){ create(:skill, name: ''Google Maps API''.downcase) }
let!(:user) { create(:user) }
before(:example) { sign_in user }
it ''finds matching records'' do
get :search, name: "Google Maps API", format: :json
expect(assigns(:skills).size).to be(1)
end
it ''finds records that start with keyword''
it ''finds records that end with keyword''
it ''finds records that contains keyword''
end
FWIW parece que los problemas se han solucionado, sin embargo, encontré el problema después de no haber leído la documentación lo suficientemente bien.
Este era nuestro código:
RSpec.configure do |config|
...
config.include Devise::TestHelpers
...
end
Esto significa que cada prueba incluirá los ayudantes de prueba, incluidos los modelos. Esto terminó siendo el problema para nosotros. Si hubiéramos leído la documentación más de cerca, habríamos notado que Devise sugiere limitarla solo a los controladores con:
RSpec.configure do |config|
...
config.include Devise::TestHelpers, type: :controller
...
end
Esto resolvió el problema para nosotros. Todas las pruebas pasan :)
La sintaxis correcta para Rails 5 / Devise (4.2.0) es
RSpec.configure do |config|
config.include Devise::Test::ControllerHelpers, :type => :controller
end
-
Devise::TestHelpers
está en desuso así que useDevise::Test::ControllerHelpers
-
:type => :controller
- para limitar solo para controladores y no modelos por ejemplo.
Me encuentro con el mismo error en los rieles 5. Aquí está mi solución
spec / rails_helper.rb
RSpec.configure do |config|
config.include Devise::TestHelpers, type: :controller
config.include Devise::TestHelpers, type: :view
config.include Warden::Test::Helpers
end
spec / controllers / your_controller_spec.rb
RSpec.describe YourController, type: :controller do
before(:all) do
user = FactoryGirl.create(:user)
login_as user, scope: :user
end
it "#index" do
get "index"
expect(response).to render_template(:index)
expect(response).to have_http_status(200)
end
$ rspec --tag focus
Run options: include {:focus=>true}
DashboardController
#index
Finished in 3.9 seconds (files took 3.5 seconds to load)
1 example, 0 failures
Mi versión de Devise es 4.2.0 así que acabo de incluir
config.include Devise::Test::ControllerHelpers, type: :controller
en mi archivo de ayuda de rieles.
Alternativamente, puede usar el mismo en su especificación como
include Devise::Test::ControllerHelpers
Para completar, con Rails 5 y RSpec me he encontrado con problemas similares cuando uso los últimos helpers, ya que deben establecerse explícitamente con el tipo cuando no se usan como superclase.
Entonces, si se encuentra recibiendo errores allí en las pruebas de su modelo, existe una posibilidad bastante buena de que el tipo no esté configurado.
Esto es lo que uso en el spec_helper:
config.include Devise::Test::ControllerHelpers, type: :controllers
config.include Devise::Test::ControllerHelpers, type: :view
config.include Devise::Test::IntegrationHelpers, type: :feature
Sé que los documentos sí lo mencionan, pero hay ocasiones en las que puede encontrarse con un blog más antiguo que le da un enfoque más antiguo, o actualizar desde una configuración anterior, y lo siguiente que sabe es que esto sucede.