Reputation: 95
I have a class with several methods, e.g.
class MyClass
def method_a(p)
method_b if p == 1
end
def method_b
some_more_stuff
end
end
And I wish to test, using RSpec, that method_a
(sometimes) calls method_b
.
it 'calls method_b if the passed parameter is 1' do
instance = spy('MyClass')
instance.method_a(1)
expect(instance).to have_received(:method_b)
end
Unfortunately, because RSpec spies don't pass on method calls to the thing they're spying on, spy.method_a
does not in fact call spy.method_b
. I've tried playing around with doubles and instance doubles, but am now horribly confused.
How can I have an RSpec double or spy or other instance object observe an instance's internal method calls without completely replacing them? I'm open to mocking out method_b
in some manner, but can't figure out how to do that properly either.
Upvotes: 3
Views: 7578
Reputation: 724
Generally I don't recommend testing things like this way, since method call is a completely internal thing. Remember, RSpec is BDD framework, and BDD is not about internal things.
However, I understand sometimes we want to test internal things using mocks and stubs. So, here's an example code:
RSpec.describe MyClass do
it 'calls method_b if the passed parameter is 1' do
instance = MyClass.new
expect(instance).to receive(:method_a).and_call_original
expect(instance).to receive(:method_b)
instance.method_a(1)
end
end
The key part is that we actually instantiate MyClass
so that we can use and_call_original
method only available on partial test doubles
.
Upvotes: 6