An action of a Rails controller makes an instance of a helper class (say SomeService
), which performs some work and returns a results, something along the lines of:
def create
...
result = SomeService.new.process
...
end
I want to stub what SomeService#process
returns.
My question is - how do I do this?
The following works:
allow_any_instance_of(SomeService).to receive(:process).and_return('what I want')
However, the rspec-mock
documentation discourages the use of allow_any_instance_of
for the reasons states here:
The rspec-mocks API is designed for individual object instances, but this feature operates on entire classes of objects. As a result there are some semantically confusing edge cases. For example in expect_any_instance_of(Widget).to receive(:name).twice it isn't clear whether each specific instance is expected to receive name twice, or if two receives total are expected. (It's the former.)
Using this feature is often a design smell. It may be that your test is trying to do too much or that the object under test is too complex.
It is the most complicated feature of rspec-mocks, and has historically received the most bug reports. (None of the core team actively use it, which doesn't help.)
I think the idea is to do something like this:
some_service = instance_double('SomeService')
allow(some_service).to receive(:process).and_return('what I want')
However, how do I make the controller use the double and not make a new instance
of SomeService
?
I usually do something like this.
let(:fake_service) { your double here or whatever }
before do
allow(SomeService).to receive(:new).and_return(fake_service)
# this might not be needed, depending on how you defined your `fake_service`
allow(fake_service).to receive(:process).and_return(fake_results)
end