无法使用rspec进行存根辅助方法

时间:2012-05-10 16:01:37

标签: ruby-on-rails ruby-on-rails-3 rspec rspec2 rspec-rails

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

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,但最终解决了一个问题。这种奇怪的行为再次猖獗,我想了解为什么这不起作用。

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

6 个答案:

答案 0 :(得分:20)

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

答案 1 :(得分: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作者的this reply,第二部分基于this Stack Overflow answer

答案 2 :(得分:3)

Rspec 3

    return this._http
    .post('/app/php/reports.php', data.toString(), 
     {headers:        this.headers})
    .toPromise()
    .then(res => res.json().data)
    .catch(this.handleError);

答案 3 :(得分:3)

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

  

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

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

解决这个问题的关键是知道辅助方法是实例方法,而对于你自己的辅助方法,它很容易实现:

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

这最终对我有用

信用到期的脚注/信用:

答案 4 :(得分:2)

对于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

答案 5 :(得分: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,除非您已全局关闭。