tutorial rails bot ruby-on-rails-4 rspec devise capybara factory-bot

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



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 use Devise::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.