Подтвердить что ты не робот

"undefined метод` env 'для nil: NilClass" в' setup_controller_for_warden 'ошибка при тестировании Devise с использованием Rspec

Я пытаюсь создать спецификацию для потока выписки с помощью factorygirl для создания пользователя, а затем использовать метод Devise sign_in для аутентификации пользователя, а затем использовать capybara, чтобы щелкнуть ссылку "Выйти".

Я получаю (как мне кажется) странную ошибку при запуске spec:

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

Здесь spec:

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

И мой user.rb factory:

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

Ошибка, кажется, запускается просто из строки include Devise::TestHelpers, поскольку я попытался комментировать весь контент спецификации и по-прежнему получить ту же ошибку.

Я думал, что помощники теста Devise будут работать из коробки; я пропустил какую-то конфигурацию? Спасибо.

4b9b3361

Ответ 1

По-видимому, есть проблемы с Devise::TestHelpers и интеграционным тестированием, поэтому, возможно, проблема здесь.

https://github.com/plataformatec/devise (упоминается в README, проблемах и т.д., также см. связанные вопросы SO):

Эти помощники не собираются работать для интеграционных тестов, управляемых Capybara или Webrat. Они предназначены для использования только с функциональными испытаниями. Вместо этого заполните форму или явно установите пользователя в сеансе;

Ответ 3

FWIW кажется, что проблемы исправлены, однако я столкнулся с проблемой после того, как вы недостаточно хорошо читали документацию.

Это наш код:

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

Это означает, что каждый тест будет включать тестовые помощники, включая модели. Это стало проблемой для нас. Если бы мы прочли документацию ближе, мы бы заметили, что Devise предлагает ограничить ее только контроллерами:

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

Это решило проблему для нас. Все прохождение тестов:)

Ответ 4

Здесь мое решение:

class ActiveSupport::TestCase
  # all the normal stuff
end

class ActionController::TestCase
  include Devise::TestHelpers    
end

Ответ 5

Как уже говорили другие, вы включаете Devise::TestHelpers. Это для контрольных контроллеров. Если вы все равно хотите автоматически войти в тестовый пользователь в своих интеграционных тестах, ознакомьтесь с официальным Инструкции по его использованию с Capybara.


Использование Devise с Capybara

В принципе, вам нужно сначала включить режим проверки Warden:

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

Затем (создайте и) войдите в свой аккаунт:

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

Пример:

# 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

Ответ 6

Я встречаю ту же ошибку на рельсах 5. Здесь мое решение

спецификации /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

спецификации/контроллеры/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 - фокус

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

Ответ 7

Версия My Devise 4.2.0, поэтому я просто включил

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

в моем справочном файле rails.

В качестве альтернативы вы можете использовать то же самое в своей спецификации, что и

include Devise::Test::ControllerHelpers

Ответ 8

Правильный синтаксис Rails 5/Devise (4.2.0) -

RSpec.configure do |config|
  config.include Devise::Test::ControllerHelpers, :type => :controller
end
  • Devise::TestHelpers устарели, поэтому используйте Devise::Test::ControllerHelpers
  • :type => :controller - ограничивать только для контроллеры, а не модели, например.

Ответ 9

У меня возникла эта проблема при попытке sign_in пользователя в переднем плане:

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

Размещение sign_in внутри до крючка приводит к:

Failure/Error: sign_in user

 NoMethodError:
   undefined method `env' for nil:NilClass

Но размещение его в примере отлично работает:

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

Но это можно улучшить, добавив sign_in в файл before (: example), который также будет работать:

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

Ответ 10

Для того, чтобы быть полным, с Rails 5 и RSpec я столкнулся с подобными проблемами при использовании последних помощников, так как они должны быть явно заданы с типом, когда он не используется в качестве суперкласса.

Итак, если вы обнаружите, что в ваших тестах есть ошибки, там довольно хороший шанс, что тип не задан.

Вот что я использую в spec_helper:

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

Я знаю, что документы действительно упоминают об этом, но бывают случаи, когда вы можете столкнуться с более старым блогом, который дает вам более старый подход или обновляется с более старой установки, а следующая вещь, которую вы знаете, это происходит.