0

I'm trying to stub out a global function called from a constructor. I'm using Rspec and Rspec-mocks. Here's the code to be tested:

def foo
  'foo'
end

class Bar
  def initialize
    @bar = foo
  end

  def bar
    @bar
  end
end

And here's the test:

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

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

The test fails with the following message:

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

       expected: "bar"
            got: "foo"

       (compared using ==)

How can I stub out the global functionfoo?

PS: expect(self).to receive(:foo) { 'bar' } works as expected if foo is being called from another global function.

Evan Kroske
  • 4,506
  • 12
  • 40
  • 59

2 Answers2

1

The simplest solution is probably uses #allow_any_instance_of, which works because "global" functions are really Kernel methods in Ruby. But since the documentation discourages stubbing classes globally, I thought I'd at least offer an alternative:

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

and

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

Of course, if possible, it would better to ditch the Kernel method and just use the class method.

0
allow_any_instance_of(Bar).to receive(:foo) { 'bar' }
Evan Kroske
  • 4,506
  • 12
  • 40
  • 59