web-dev-qa-db-fra.com

"méthode non définie` env 'pour nil: NilClass "dans l'erreur' setup_controller_for_warden 'lors du test de Devise à l'aide de Rspec

J'essaie de créer une spécification pour un flux de déconnexion en utilisant factorygirl pour créer un utilisateur, puis en utilisant sign_in méthode pour authentifier l'utilisateur, puis utilisez capybara pour cliquer sur le lien "Déconnexion".

Je reçois (ce qui me semble être) une étrange erreur lorsque j'exécute la spécification:

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

Voici la spécification:

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

Et mon user.rb usine:

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

L'erreur semble être déclenchée simplement à partir de la ligne include Devise::TestHelpers, car j'ai essayé de commenter tout le contenu de la spécification et j'obtiens toujours la même erreur.

Je pensais que les assistants de test Devise fonctionneraient hors de la boîte; ai-je manqué une configuration? Merci.

37
jpalmieri

Apparemment, il y a des problèmes avec Devise::TestHelpers et les tests d'intégration, c'est peut-être le problème ici.

https://github.com/plataformatec/devise (mentionné dans README, Issues, etc.; voir également les SO questions connexes):

Ces assistants ne vont pas travailler pour des tests d'intégration pilotés par Capybara ou Webrat. Ils sont destinés à être utilisés uniquement avec des tests fonctionnels. Remplissez plutôt le formulaire ou définissez explicitement l'utilisateur en session;

20
TK-421

Dans Rails 5, vous devez inclure Devise::Test::IntegrationHelpers au lieu Devise::Test::ControllerHelpers:

# Rails_helper.rb
config.include Devise::Test::IntegrationHelpers, type: :feature

Voir plus:

40
user1519240

FWIW, il semble que les problèmes aient été corrigés, mais j'ai rencontré le problème après avoir mal lu la documentation.

C'était notre code:

RSpec.configure do |config|
  ...  
  config.include Devise::TestHelpers
  ...
end

Cela signifie que chaque test comprendra les assistants de test, y compris les modèles. Cela s'est avéré être le problème pour nous. Si nous avions lu la documentation de plus près, nous aurions remarqué que Devise suggère de la limiter aux seuls contrôleurs avec:

RSpec.configure do |config|
  ...  
  config.include Devise::TestHelpers, type: :controller
  ...
end

Cela a résolu le problème pour nous. Tous les tests réussissent :)

18
NoahNoahNoah

Voici ma solution:

class ActiveSupport::TestCase
  # all the normal stuff
end

class ActionController::TestCase
  include Devise::TestHelpers    
end
11
Will Taylor

Je rencontre la même erreur sur Rails 5. Voici ma solution

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 - focus tag

Run options: include {:focus=>true}
DashboardController
#index
Finished in 3.9 seconds (files took 3.5 seconds to load)
1 example, 0 failures
8
Ray Lee

Comme d'autres l'ont déjà dit, vous incluez le Devise::TestHelpers. C'est pour tester les contrôleurs . Si vous souhaitez toujours vous connecter automatiquement à un utilisateur de test dans vos tests d'intégration, consultez l'officiel Concevoir des instructions pour l'utiliser avec Capybara.


Utiliser Devise avec Capybara

Fondamentalement, ce que vous devez faire est d'abord activer le mode de test de Warden:

include Warden::Test::Helpers
Warden.test_mode!

Ensuite, (créez et) connectez votre utilisateur:

user = FactoryGirl.create(:user)
login_as(user, scope: :user)

Exemple:

# 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
7
Sheharyar

Pour être complet, avec Rails 5 et RSpec, j'ai rencontré des problèmes similaires lors de l'utilisation des derniers assistants, car ils doivent être définis explicitement avec le type lorsqu'ils ne sont pas utilisés en tant que superclasse.

Donc, si vous vous retrouvez à recevoir des erreurs dans vos tests de modèle, il y a de fortes chances que le type ne soit pas défini.

Voici ce que j'utilise dans le spec_helper:

  config.include Devise::Test::ControllerHelpers, type: :controller
  config.include Devise::Test::ControllerHelpers, type: :view
  config.include Devise::Test::IntegrationHelpers, type: :feature

Je sais que les documents le mentionnent, mais il peut arriver que vous rencontriez un ancien blog qui vous donne une approche plus ancienne ou une mise à niveau à partir d'une ancienne configuration, et la prochaine chose que vous savez, c'est que cela se produit.

2
DBrown

La syntaxe correcte pour Rails 5/Devise (4.2.0) est

RSpec.configure do |config|
  config.include Devise::Test::ControllerHelpers, :type => :controller
end
  • Devise::TestHelpers sont obsolètes, utilisez donc Devise::Test::ControllerHelpers
  • :type => :controller - pour limiter uniquement les contrôleurs et non les modèles par exemple.
2
Ivailo Bardarov

Ma version Devise est 4.2.0 donc je viens de l'inclure

config.include Devise::Test::ControllerHelpers, type: :controller

dans mon Rails helper file.

Alternativement, vous pouvez utiliser le même dans vos spécifications que

include Devise::Test::ControllerHelpers
2
Mayuresh Srivastava

J'avais ce problème en essayant de sign_in un utilisateur dans un hook avant:

before(:context) do
  create(:skill, name: 'Google Maps API'.downcase)
  user = create(:user)
  sign_in user
end

Placement sign_in à l'intérieur du crochet avant conduit à:

Failure/Error: sign_in user

 NoMethodError:
   undefined method `env' for nil:NilClass

Mais le placer dans un exemple fonctionne très 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

Mais cela peut être amélioré, en plaçant le signe_in dans un avant (: exemple) qui fonctionnera également:

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
2
juliangonzalez