无法使用rspec存储辅助方法

我试图在我的控制器中定义的助手上存根方法。 例如:

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 

我在这里问了一个类似的问题,但最终解决了一个问题。 这种奇怪的行为再次崛起,我想了解为什么这不起作用。

更新 :我发现在helper.stub!(...)之前调用controller.stub!(:current_user).and_return(@user)是导致此行为的原因。 这很容易修复spec/support/authentication.rb ,但这是Rspec中的一个错误吗? 我不明白为什么如果它已经存在于控制器上,那么它将无法在助手上存根方法。

试试这个,它对我有用:

 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的回答 。

更新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/

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") 

在RSpec 3.5 RSpec中,似乎无法从it块访问helper程序。 (它会给你以下信息:

helper在示例(例如it块)中或从在示例范围内运行的构造(例如beforelet等)中不可用。 它仅适用于示例组(例如, describecontext块)。

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

解决这个问题的关键是知道帮助器方法是实例方法,而对于你自己的帮助器方法,它很容易做到这一点:

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

这是最终为我工作的

脚注/信用到期信用:

  • 超级道具由Johnny Ji撰写的一篇关于他们在帮助/实例方法中挣扎的博客文章

在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