There are already questions similar to this, but they all override the return values to nil
unless .and_return
is called as well
PROBLEM
I am wondering if there is a way to just check if a method is called using expect_any_instance_of(Object).to receive(:somemethod)
and it runs normally without overriding or affecting the return value of .somemethod
.
Consider the following:
# rspec
it 'gets associated user' do
expect_any_instance_of(Post).to receive(:get_associated_user)
Manager.run_processes
end
# manager.rb
class Manager
def self.run_processes
associated_user = Category.first.posts.first.get_associated_user
associated_user.destroy!
end
end
The spec above although will work because :get_associated_user
is called in the run_processes
, however it raises NoMethodError: undefined method 'destroy!' for NilClass
precisely because I mocked the :get_associated_user
for any instance of Post.
I could add a .and_return
method like expect_any_instance_of(Post).to receive(:get_associated_user).and_return(User.first)
so that it will work without raising that error, but that already is a mocked return value (which might affect the rest of the code below it), and not the correct expected value it should have returned at the time the method is called.
I can however specify .and_return(correct_user)
where correct_user
is the user that is going to be the same return value as if it has ran normally. However, this will need me to mock every return value in the sequence Category.first.posts.first.get_associated_user
just so that it will work normally. The actual problem is a lot more complex than above, therefore stubbing is not really a possible solution in my case.
You can use
and_call_original
on the fluent interface to "pass through" the received message to the original method.https://www.relishapp.com/rspec/rspec-mocks/v/2-14/docs/message-expectations/calling-the-original-method
expect_any_instance_of(Post).to receive(:get_associated_user).and_call_original
However the use of expect_any_instance_of
might be telling you that you have a code smell and you should be testing the behavior - not the implementation.
# test what it does - not how it does it.
it 'destroys the associated user' do
expect { Manager.run_processes }.to change(Category.first.posts.first.users, :count).by(-1)
end
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With