web-dev-qa-db-ja.com

Rspecを使用してDeviseをテストする際の「setup_controller_for_warden」エラーの「nil:NilClassの未定義メソッド「env」」

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のテストヘルパーはそのまま使用できると思いました。いくつかの構成を見逃しましたか?ありがとう。

37
jpalmieri

どうやらDevise::TestHelpersと統合テストに問題があるので、おそらくここが問題です。

https://github.com/plataformatec/devise (README、Issueなどで言及。関連するSOの質問)も参照):

これらのヘルパーは、CapybaraまたはWebratが推進する統合テストでは機能しません。機能テストでのみ使用することを意図しています。代わりに、フォームに入力するか、セッションで明示的にユーザーを設定します。

20
TK-421

Rails 5では、Devise::Test::IntegrationHelpers代わりにDevise::Test::ControllerHelpers

# Rails_helper.rb
config.include Devise::Test::IntegrationHelpers, type: :feature

続きを見る:

40
user1519240

FWIW問題が修正されたようですが、ドキュメントを十分に読んでいないので問題に遭遇しました。

これが私たちのコードでした:

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

これは、すべてのテストにモデルを含むテストヘルパーが含まれることを意味します。これが私たちの問題でした。ドキュメンテーションを詳しく読んだら、Deviseが以下のコントローラーのみに限定することを提案していることに気づいたでしょう。

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

これで問題が解決しました。すべてのテストに合格:)

18
NoahNoahNoah

私のソリューションは次のとおりです。

class ActiveSupport::TestCase
  # all the normal stuff
end

class ActionController::TestCase
  include Devise::TestHelpers    
end
11
Will Taylor

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/controllers/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
8
Ray Lee

他の人がすでに言っているように、あなたはDevise::TestHelpers。これは、 コントローラのテスト です。それでも統合テストでテストユーザーに自動的にログインしたい場合は、公式Capybaraで使用するための手順の説明


CapybaraでDeviseを使用する

基本的に、あなたがする必要があるのは、最初にワーデンのテストモードを有効にすることです:

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
7
Sheharyar

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

私はドキュメントがこれに言及していることを知っていますが、古いアプローチを提供する古いブログを横断したり、古いセットアップからアップグレードしたりすることがあります。

2
DBrown

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-モデルのみではなく、コントローラーのみを制限します。
2
Ivailo Bardarov

私のDeviseバージョンは4.2.0ですので、

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

my Railsヘルパーファイル。

または、仕様で同じものを使用できます

include Devise::Test::ControllerHelpers
2

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
2
juliangonzalez