27

コントローラで定義されているヘルパーでメソッドをスタブしようとしています。例えば:

class ApplicationController < ActionController::Base
  def current_user
    @current_user ||= authenticated_user_method
  end
  helper_method :current_user
end

module SomeHelper
  def do_something
    current_user.call_a_method
  end
end

私のRspecでは:

describe SomeHelper
  it "why cant i stub a helper method?!" do
    helper.stub!(:current_user).and_return(@user)
    helper.respond_to?(:current_user).should be_true # Fails
    helper.do_something # Fails 'no method current_user'
  end
end

spec/support/authentication.rb

module RspecAuthentication
  def sign_in(user)
    controller.stub!(:current_user).and_return(user)
    controller.stub!(:authenticate!).and_return(true)

    helper.stub(:current_user).and_return(user) if respond_to?(:helper)
  end
end

RSpec.configure do |config|
  config.include RspecAuthentication, :type => :controller
  config.include RspecAuthentication, :type => :view
  config.include RspecAuthentication, :type => :helper
end

私はここで同様の質問をしましたが、回避策に落ち着きました。この奇妙な振る舞いが再び忍び寄ってきたので、なぜこれが機能しないのかを理解したいと思います。

更新controller.stub!(:current_user).and_return(@user):前に呼び出すhelper.stub!(...)ことがこの動作の原因であることがわかりました。これは簡単に修正できますがspec/support/authentication.rb、これはRspecのバグですか?メソッドがすでにコントローラーでスタブされている場合、ヘルパーでメソッドをスタブできないと予想される理由がわかりません。

4

6 に答える 6

22

Matthew Ratzloffの回答を更新してください:インスタンスオブジェクトとスタブは必要ありません!非推奨になりました

it "why can't I stub a helper method?!" do
  helper.stub(:current_user) { user }
  expect(helper.do_something).to eq 'something'
end

編集。RSpec3の方法は次のようにstub!なります。

allow(helper).to receive(:current_user) { user }

参照:https ://relishapp.com/rspec/rspec-mocks/v/3-2/docs/

于 2013-11-20T05:17:59.913 に答える
13

RSpec 3.5 RSpecでは、ブロックhelperからアクセスできなくなったようです。it(次のメッセージが表示されます:

helper例内(itブロックなど)から、または例のスコープ内で実行される構成要素( beforeletなど)からは使用できません。サンプルグループ(例:adescribeまたはcontextブロック)でのみ使用できます。

(この変更に関するドキュメントが見つからないようです。これはすべて実験的に得られた知識です)。

これを解決するための鍵は、ヘルパーメソッドがインスタンスメソッドであり、独自のヘルパーメソッドの場合はこれを簡単に実行できることを知っていることです。

allow_any_instance_of( SomeHelper ).to receive(:current_user).and_return(user) 

これが最終的に私のために働いたものです

脚注/クレジットクレジットの期限:

于 2017-06-18T14:35:31.117 に答える
8

これを試してみてください、それは私のために働きました:

describe SomeHelper
  before :each do
    @helper = Object.new.extend SomeHelper
  end

  it "why cant i stub a helper method?!" do
    @helper.stub!(:current_user).and_return(@user)
    # ...
  end
end

最初の部分はRSpecの作成者によるこの回答に基づいており、2番目の部分はこのStackOverflowの回答に基づいています

于 2012-07-13T04:41:23.533 に答える
5

Rspec 3

  user = double(image: urlurl)
  allow(helper).to receive(:current_user).and_return(user)
  expect(helper.get_user_header).to eq("/uploads/user/1/logo.png")
于 2016-09-22T05:19:19.413 に答える
3

これは、RSpec3の場合に機能しました。

let(:user) { create :user }
helper do
  def current_user; end
end
before do
  allow(helper).to receive(:current_user).and_return user
end
于 2017-10-06T12:46:50.587 に答える
0

RSpec 3.10以降、この手法は機能します。

  before do
    without_partial_double_verification { 
      allow(view).to receive(:current_user).and_return(user)
    }
  end

ラッパーをグローバルにオフにしない限り、without_partial_double_verificationラッパーは回避するために必要です。MockExpectationError

于 2021-07-23T17:22:03.280 に答える