web-dev-qa-db-ja.com

RSpec:継承されたメソッドcurrent_userをスタブする方法(Deviseなし)?

MHartlの RoR4チュートリアル に基づいたコントローラーがあります。

MHartlと同じように、私はDeviseを使用していません、私は 自分の認証システムをロールしました

ビューに_UsersController#Edit_への呼び出しがあり、コントローラーが_current_user.admin?_を呼び出すため、_@path_switch = path_switch_のRSpecに問題があります。

私は次の行に沿ってRSpecエラーを受け取り続けます:

_1) User Pages Edit 
 Failure/Error: visit edit_user_path(user)
 NoMethodError:
   undefined method `admin?' for nil:NilClass
 # ./app/controllers/users_controller.rb:106:in `path_switch'
 # ./app/controllers/users_controller.rb:53:in `edit'
 # ./spec/requests/user_pages_spec.rb:54:in `block (3 levels) in <top (required)>'
_

UsersController:

_class UsersController < ApplicationController
  ...
  def edit
    @user = User.find(params[:id])
    @path_switch ||= path_switch                        #error
  end
  ...
  def path_switch
    if current_user.admin?                               #error
      users_path
    else
      root_path
    end
  end
end
_

私はこれを見つけました 本当に役立つ記事 それは私が正しい軌道に乗っているという希望を与えますが、それを機能させることができません。

これが私が得た限りです(更新):

user_pages_spec.rb:

_require 'spec_helper'
require 'support/utilities'

describe "User Pages" do
  #include SessionsHelper

  let(:user) { FactoryGirl.create(:user) }
  let(:current_user) {user}

  subject { page }

  describe "Edit" do
    before do
      sign_in(user)
      visit edit_user_path(user) 
    end

    it '(check links and content)' do
      should have_button('Submit')
      should have_link('Cancel')
      should have_content(user.fname+"\'s profile")
    end
   ...
  end
...
end
_

しかし、_current_user_はまだ戻ってきますnil

どんな助け/ガイダンスもありがたいです。ありがとう!


_include SessionsHelper_を私の_user_pages_edit.rb_の上部の記述ブロックに追加すると、そのヘルパーからのsign_in(path)を使用しようとするようです。 RSpecと_cookies.permanent_ の間の問題を作成します。だからそれはバストです。

残念ながら、これは私を_.admin?_エラーに戻します。

_current_user.admin?_への呼び出しは2つあります

1つはコントローラ内にあります:

_  def path_switch
    if current_user.admin?    #error current_user == nil
      users_path
    else
      root_path
    end
  end
_

1つはERBとしてビューにあります:

_<% if current_user.admin? %>
  <div class="row  col-xs-6 col-sm-6 col-md-3">
    <div class="input-group input-selector">
    ...
_

_current_user.admin = true_を設定し、それをコントローラー(そしてできればビュー)に渡してページを読み込めるようにする方法を理解するだけです。これを行うには、_current_user = user_なので_user.admin == true_を設定するだけです。

24
Chiperific

また働く

user = create(:user) #FactoryBot

allow(controller).to receive(:current_user).and_return(user)
5
user2322409

コントローラの単体テストを実行している場合は、単にcurrent_user beforeブロックでは、次のようになります。

let(:user) { ... }

# RSpec version <= 2 syntax:
before { controller.stub(:current_user) { user } }

# RSpec version >= 3 syntax:
before { allow(controller).to receive(:current_user) { user } }

機能テストまたはリクエストテストを実行している場合は、データベースにユーザーを作成して実際のログインを実行し、このユーザー資格情報でログインページを通過することをお勧めします


ここでは機能テストを行っているようですが、ユーザーレコードの作成を実行してログインを実行するヘルパーを作成する必要があります。

さらに、テストの実行中に多くの時間を得るための機能テストでは、アサーションを同じブロックにグループ化することをためらわないでください。明らかに、代わりに:

it { should have_button('Submit')}
it { should have_link('Cancel')}
it { should have_content(user.fname+"\'s profile")}

あなたは書ける

it 'check links and content' do
  should have_button('Submit')
  should have_link('Cancel')
  should have_content(user.fname+"\'s profile")
end

これにより、フィーチャー環境の複数のセッションを生成したり、何度もログインしたりする必要がなくなります。

36
Benj

私にとっては、

before { controller.stub!(:current_user).and_return(user) }
1
leompeters

レガシーRails 4アプリで同じ問題が発生し、Rspecビューのテストケース this テストケースに基づいて私の解決策を実行しました。

最初に、コントローラーインスタンスで不足しているヘルパーメソッドを定義するヘルパーを定義します

# /spec/support/concerns/view_helper.rb
module ViewHelper
  def include_current_user_helper(&block)
    controller.singleton_class.class_eval do
      define_method :current_user, &block
      helper_method :current_user
    end
  end
end

次に、Rspecを構成してすべてのビューヘルパーに含めます

# spec/Rails_helper.rb
# ...
Dir[Rails.root.join('spec/support/**/*.rb')].each { |f| require f }

RSpec.configure do |config|
  # ...
  config.include ViewHelper, type: :view
end

そして、ビュースペックでは、このように呼ばれています

RSpec.describe 'something' do
  let!(:user) { FactoryGirl.create(:user) } # Note the "!" there
  before { include_current_user_helper { user } }

  # do stuff
end

注:ブロック内のコンテンツはテストスコープ外で遅延実行されるため、letをbangで呼び出すことは重要です。そうでない場合、ユーザーは無効になります。

0
R. Sierra