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

编辑。RSpec 3 的方法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等)获得。它仅适用于示例组(例如 adescribecontext块)。

(我似乎找不到有关此更改的任何文档,这是通过实验获得的所有知识)。

解决这个问题的关键是知道辅助方法是实例方法,并且对于您自己的辅助方法,这样做很容易:

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 作者的这个回复,第二部分基于这个 Stack Overflow 的答案

于 2012-07-13T04:41:23.533 回答
5

规格 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

在 RSpec 3 的情况下,这对我有用:

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需要包装器来避免 a 。MockExpectationError

于 2021-07-23T17:22:03.280 回答