无法使用 rspec 存根辅助方法
Posted
技术标签:
【中文标题】无法使用 rspec 存根辅助方法【英文标题】:Unable to stub helper method with rspec 【发布时间】:2012-05-19 06:11:01 【问题描述】:我正在尝试在我的控制器中定义的帮助程序上存根方法。例如:
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
我问了一个类似的问题here,但解决了一个问题。这种奇怪的行为再次蔓延,我想了解为什么这不起作用。
更新:我发现在helper.stub!(...)
之前调用controller.stub!(:current_user).and_return(@user)
是导致这种行为的原因。这很容易在spec/support/authentication.rb
中修复,但这是 Rspec 中的错误吗?我不明白为什么如果它已经在控制器上存根,为什么不能在助手上存根方法。
【问题讨论】:
尝试通过 ApplicationController 对方法进行存根,因为这是定义它的地方。ApplicationController.stub(:current_user => @user)
编辑:现在我想这可能行不通。
不,它没有用。我也试过any_instance
,但没有运气。我实际上已经让它工作了,但我有点困惑(可能发现了 rspec 的错误)。我会尽快更新问题。
听起来像一个错误。绝对值得在github.com/rspec/rspec-mocks/issues 提交问题(并尝试使用最新版本)。
创建票证:github.com/rspec/rspec-mocks/issues/135
我也有同样的问题,请问有解决办法吗?
【参考方案1】:
更新 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
编辑。 stub!
的 RSpec 3 方式是:
allow(helper).to receive(:current_user) user
见:https://relishapp.com/rspec/rspec-mocks/v/3-2/docs/
【讨论】:
我修正了 RSpec 3 的答案。【参考方案2】:在 RSpec 3.5 RSpec 中,似乎无法再从 it
块访问 helper
。 (它会给你以下信息:
helper
在示例中(例如it
块)或在示例范围内运行的构造(例如before
、let
等)中不可用。它仅适用于示例组(例如describe
或context
块)。
(我似乎找不到任何有关此更改的文档,这都是通过实验获得的知识)。
解决这个问题的关键是知道辅助方法是实例方法,并且对于您自己的辅助方法,这样做很容易:
allow_any_instance_of( SomeHelper ).to receive(:current_user).and_return(user)
这就是最终对我有用的方法
脚注/贷记到期:
Super Props to a blog entry by Johnny Ji about their struggles stubbing helper/instance methods【讨论】:
【参考方案3】:试试这个,它对我有用:
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作者this reply,第二部分基于this Stack Overflow answer。
【讨论】:
... 然后测试实际上需要测试@helper,而不是 SomeHelper。【参考方案4】: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")
【讨论】:
【参考方案5】:这在 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
【讨论】:
非常聪明。首先,您在助手中定义缺少的方法(来自另一个助手,控制器),然后将其存根。def ...
块可以直接使用user
,所以不需要存根吗?【参考方案6】:
从 RSpec 3.10 开始,此技术将起作用:
before do
without_partial_double_verification
allow(view).to receive(:current_user).and_return(user)
end
需要without_partial_double_verification
包装器来避免MockExpectationError
,除非您已全局关闭它。
【讨论】:
以上是关于无法使用 rspec 存根辅助方法的主要内容,如果未能解决你的问题,请参考以下文章