"неопределенный метод" env "для nil:NilClass" в ошибке "Setup controller for warden" при тестировании устройства с использованием Rspec
Я пытаюсь создать спецификацию для потока выхода, используя factorygirl для создания пользователя, а затем использовать Devise sign_in
метод для аутентификации пользователя, затем используйте capybara, чтобы щелкнуть ссылку "выйти".
Я получаю (что мне кажется) странную ошибку, когда я запускаю спецификацию:
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
вот спек:
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
фабрика:
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 будут работать из коробки; я пропустил какую-то конфигурацию? Спасибо.
10 ответов
по-видимому, есть проблемы с Devise::TestHelpers
и интеграционное тестирование, так что, возможно, в этом проблема.
https://github.com/plataformatec/devise (упоминается в README, выпусках и т. д.; Также см. связанные вопросы SO):
эти помощники не будут работать для интеграционных тестов, управляемых Capybara или Webrat. Они предназначены для использования только с функциональными пробами. Вместо этого заполните форму или явно укажите пользователя в сеанс;
в Rails 5 Вы должны включить Devise::Test::ControllerHelpers
:
# rails_helper.rb
config.include Devise::Test::IntegrationHelpers, type: :feature
Посмотреть подробнее:
FWIW похоже, что проблемы были исправлены, однако я столкнулся с проблемой после недостаточно хорошего чтения документации.
Это был наш код:
RSpec.configure do |config|
...
config.include Devise::TestHelpers
...
end
Это означает, что каждый тест будет включать помощников по тестированию, включая модели. Это стало проблемой для нас. Если бы мы прочитали документацию ближе, мы бы заметили, что Devise предлагает ограничить ее только контроллерами с:
RSpec.configure do |config|
...
config.include Devise::TestHelpers, type: :controller
...
end
это решило проблему для нас. Все тесты проходя:)
вот мое решение:
class ActiveSupport::TestCase
# all the normal stuff
end
class ActionController::TestCase
include Devise::TestHelpers
end
как уже говорили другие, вы в том числе 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
я встречаю ту же ошибку на rails 5. Вот мое решение
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 / контроллеры / 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
моя версия Devise-4.2.0, поэтому я просто включил
config.include Devise::Test::ControllerHelpers, type: :controller
в моем файле помощника rails.
в качестве альтернативы вы можете использовать то же самое в своей спецификации как
include Devise::Test::ControllerHelpers
правильный синтаксис для 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
- ограничить только для например, контроллеры, а не модели.
у меня была эта проблема при попытке 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 в A перед (: пример), который также будет работать:
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
чтобы быть полным, с 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
Я знаю, что документы упоминают об этом, но бывают случаи, когда вы можете запустить в более старом блоге, который дает вам более старый подход или обновление из более старой установки, и следующее, что вы знаете, это происходит.