如何存根从构造函数调用的全局函数?

时间:2019-04-11 18:55:27

标签: ruby rspec rspec-mocks

我正在尝试存根从构造函数调用的全局函数。我正在使用Rspec和Rspec-mocks。这是要测试的代码:

def foo
  'foo'
end

class Bar
  def initialize
    @bar = foo
  end

  def bar
    @bar
  end
end

这是测试:

describe 'bar'
  it 'calls foo' do
    expect(self).to receive(:foo) { 'bar' }

    expect(Bar.new.bar).to eq('bar')
  end
end

测试失败,并显示以下消息:

     Failure/Error: expect(Bar.new.bar).to eq('bar')

       expected: "bar"
            got: "foo"

       (compared using ==)

如何将全局函数存根foo

PS:如果从另一个全局函数中调用expect(self).to receive(:foo) { 'bar' },则foo会按预期工作。

2 个答案:

答案 0 :(得分:1)

最简单的解决方案可能是使用#allow_any_instance_of,这是有效的,因为“全局”函数实际上是Ruby中的Kernel方法。但是,由于the documentation discourages在全球范围内存根类,所以我认为我至少会提供一种替代方法:

def foo
  'foo'
end

class Bar
  def self.get_foo
    foo
  end

  def initialize
    @bar = self.class.get_foo
  end

  def bar
    @bar
  end
end

describe Bar do
  it 'gets foo' do
    expect(Bar).to receive(:get_foo).and_return('bar')

    expect(Bar.new.bar).to eq('bar')
  end
end

当然,如果可能的话,最好放弃Kernel方法而只使用class方法。

答案 1 :(得分:0)

allow_any_instance_of(Bar).to receive(:foo) { 'bar' }