web-dev-qa-db-fra.com

Rails, Devise, Rspec: Méthode non définie 'sign_in'

J'essaie d'écrire des tests Rspec dans Rails, à l'aide des méthodes d'assistance Devise pour la connexion et la déconnexion. La méthode sign_in ne fonctionne pas. Cependant, cela fonctionnait plus tôt, avant une multitude de changements dans l'application.

Choses que j'ai essayées:

  • J'inclus les aides de test dans Rspec.configure.
  • Utiliser le login_as de Warden
  • Effacement du cache Rails.
  • Se débarrasser de Capybara pour voir si cela causait le problème
  • Je ne mets pas la session explicitement dans les spécifications de mon contrôleur (par exemple, pas de valid_session)

Jusqu'à présent, pas de dés. Que dois-je faire différemment pour tester mes contrôleurs avec un utilisateur connecté?

Message d'erreur: 

 OrderItemsController GET #index renders the :index view
 Failure/Error: sign_in :admin
 NoMethodError:
      undefined method `sign_in' for #  <RSpec::ExampleGroups::OrderItemsController_2::GETIndex:0x00000102c002d0>
 # ./spec/controllers/order_items_controller_spec.rb:6:in `block (2 levels) in <top (required)>'

Spécifications du contrôleur

require 'spec_helper'

describe OrderItemsController do
    before (:each) do
        admin = create(:admin)
        sign_in :admin
    end

    describe "GET #index" do
        it "renders the :index view" do
            get :index
            expect( response ).to render_template :index
        end
    end
end

spec_helper.rb

require 'rspec/Rails'
require 'capybara/rspec'

RSpec.configure do |config|

  config.include ApplicationHelper
  config.include ControllersHelper
  config.include UsersHelper
  config.include Devise::TestHelpers, type: :controller
  config.include FactoryGirl::Syntax::Methods

end

Gemfile

group :development, :test do
    gem 'rspec-Rails', '~> 3.0.0.beta'
    gem 'capybara'
    gem 'factory_girl_Rails'
    gem 'faker'
    gem 'dotenv-Rails'
    gem 'guard'
    gem 'guard-annotate'
    gem 'guard-rspec', require: false
    gem 'guard-livereload', require: false
    gem 'foreman'
end

usines/utilisateur.rb

FactoryGirl.define do

    factory :user do
        first                   { Faker::Name.first_name }
        last                    { Faker::Name.last_name }
        email                   { Faker::Internet.email }
        admin                   false
        password                "secrets1"
        password_confirmation   "secrets1"
        confirmed_at            Date.today

        factory :admin do
            admin               true
        end
    end
end

Merci d'avance.

29
steel

Avez-vous récemment migré vers RSpec 3 comme moi? Cela provient de de la documentation RSpec 3 :

Ajout automatique de métadonnées Les versions de RSpec antérieures à la version 3.0.0 ajoutaient automatiquement des métadonnées aux spécifications basées sur leur emplacement sur le système de fichiers. C'était à la fois déroutant pour les nouveaux utilisateurs et non souhaitable pour certains utilisateurs vétérans.

Dans RSpec 3, ce comportement doit être explicitement activé:

​# spec/Rails_helper.rb
RSpec.configure do |config|
    config.infer_spec_type_from_file_location!
end

Puisque ce comportement supposé est tellement répandu dans les tutoriels, le paramètre par défaut La configuration générée par Rails génère rspec: l’installation le permet.

Si vous suivez la structure de répertoires canoniques listée ci-dessus et que vous avez configuré infer_spec_type_from_file_location !, RSpec sera automatiquement inclure les fonctions de support correctes pour chaque type.

Après avoir ajouté cet extrait de configuration, je n'ai plus besoin de spécifier le type de spécification (par exemple type: :controller).

29
Tyler Collier

J'ai trouvé une solution. J'ai explicitement défini le bloc Describe de l'automate en tant que type d'automate.

describe OrderItemsController, :type => :controller do

Je ne comprends toujours pas pourquoi ce code fonctionnait auparavant mais a maintenant besoin de cette déclaration explicite (apparemment redondante). Quoi qu'il en soit, j'apprécierais d'apprendre ce qui s'est passé ici. Merci!

8
steel

Je peux vous donner un exemple (fonctionne pour moi - rspec/capybara/simplecov etc.)

spec/spec_helper.rb

 require 'capybara/rspec'
 require 'capybara/Rails'

 RSpec.configure do |config|
  config.use_transactional_fixtures = true

  config.infer_base_class_for_anonymous_controllers = false

  config.include FactoryGirl::Syntax::Methods
  config.include Devise::TestHelpers, type: :controller
  config.include Capybara::DSL
  config.include Warden::Test::Helpers
  config.include Rails.application.routes.url_helpers
end

spec/integration/user_flow_spec.rb

require 'spec_helper'

feature 'Verify contract' do
  # Create employee
  let(:employee) { create(:employee) }
  let (:book) { create(:book) }

  # Sign in employee before each test!
  before :each do
    login_as employee, scope: :user
  end

  scenario 'create book' do
    # Visit Index and click to create
    visit employee_books_path
    click_link 'Create'
    expect(current_path).to eq(employee_books_path)
  end
end

J'espère que tout ira bien :) Je pense que votre problème est absent.

6
Jan Strnádek

Vous pouvez utiliser l’assistant Devise dans le fichier spec/spec_helper.rb:

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

Pour Rails 5 et Rspec 3, vous devez ajouter ceci dans votre spec_helper.rb.

config.include Devise :: Test :: ControllerHelpers, tapez:: contrôleur

0
Andrey