"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 будут работать из коробки; я пропустил какую-то конфигурацию? Спасибо.
Ответы
Ответ 1
По-видимому, есть проблемы с Devise::TestHelpers
и интеграционным тестированием, поэтому, возможно, проблема здесь.
https://github.com/plataformatec/devise (упоминается в README, проблемах и т.д., также см. связанные вопросы SO):
Эти помощники не собираются работать для интеграционных тестов, управляемых Capybara или Webrat. Они предназначены для использования только с функциональными испытаниями. Вместо этого заполните форму или явно установите пользователя в сеансе;
Ответ 2
В Rails 5 вы должны включить Devise::Test::IntegrationHelpers
вместо Devise::Test::ControllerHelpers
:
# rails_helper.rb
config.include Devise::Test::IntegrationHelpers, type: :feature
Подробнее:
Ответ 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
Я знаю, что документы действительно упоминают об этом, но бывают случаи, когда вы можете столкнуться с более старым блогом, который дает вам более старый подход или обновляется с более старой установки, а следующая вещь, которую вы знаете, это происходит.