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のテストヘルパーはそのまま使用できると思いました。いくつかの構成を見逃しましたか?ありがとう。
どうやらDevise::TestHelpers
と統合テストに問題があるので、おそらくここが問題です。
https://github.com/plataformatec/devise (README、Issueなどで言及。関連するSOの質問)も参照):
これらのヘルパーは、CapybaraまたはWebratが推進する統合テストでは機能しません。機能テストでのみ使用することを意図しています。代わりに、フォームに入力するか、セッションで明示的にユーザーを設定します。
Rails 5では、Devise::Test::IntegrationHelpers
代わりに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
Rails 5.で同じエラーに遭遇しました。これが私の解決策です
RSpec.configure do |config|
config.include Devise::TestHelpers, type: :controller
config.include Devise::TestHelpers, type: :view
config.include Warden::Test::Helpers
end
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
Run options: include {:focus=>true}
DashboardController
#index
Finished in 3.9 seconds (files took 3.5 seconds to load)
1 example, 0 failures
他の人がすでに言っているように、あなたはDevise::TestHelpers
。これは、 コントローラのテスト です。それでも統合テストでテストユーザーに自動的にログインしたい場合は、公式Capybaraで使用するための手順の説明。
基本的に、あなたがする必要があるのは、最初にワーデンのテストモードを有効にすることです:
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とRSpecを使用して完全にするために、スーパークラスとして使用しない場合はタイプを明示的に設定する必要があるため、最新のヘルパーを使用すると同様の問題が発生します。
そのため、モデルテストでエラーが発生した場合は、タイプが設定されていない可能性がかなりあります。
Spec_helperで使用するものは次のとおりです。
config.include Devise::Test::ControllerHelpers, type: :controller
config.include Devise::Test::ControllerHelpers, type: :view
config.include Devise::Test::IntegrationHelpers, type: :feature
私はドキュメントがこれに言及していることを知っていますが、古いアプローチを提供する古いブログを横断したり、古いセットアップからアップグレードしたりすることがあります。
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
-モデルのみではなく、コントローラーのみを制限します。私のDeviseバージョンは4.2.0ですので、
config.include Devise::Test::ControllerHelpers, type: :controller
my Railsヘルパーファイル。
または、仕様で同じものを使用できます
include Devise::Test::ControllerHelpers
Beforeフックのユーザーをsign_in
しようとしたときにこの問題が発生していました。
before(:context) do
create(:skill, name: 'Google Maps API'.downcase)
user = create(:user)
sign_in user
end
Beforeフック内に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