Read more

Heads up: expect(object).to receive(:method_name) does not execute the original implementation of the method

Tanja
January 24, 2023Software engineer at makandra GmbH

Let's assume that we have a model Movie that registers a callback function when a new instance of Movie is created (Note: For the purpose of this card it is not important what that callback does or which type of callback it is).

Illustration web development

Do you need DevOps-experts?

Your development team has a full backlog? No time for infrastructure architecture? Our DevOps team is ready to support you!

  • We build reliable cloud solutions with Infrastructure as code
  • We are experts in security, Linux and databases
  • We support your dev team to perform
Read more Show archive.org snapshot

This is how we test whether the callback function (here it is named :my_method) is called when a new movie is created:

expect_any_instance_of(Movie).to receive(:my_method)
create(:movie)  # <-- this is where the method :my_method should be called

You might expect that when calling create(:movie), the callback function will be executed and whatever it does will happen and will have effect. But what we can observe is that the behaviour of the callback function :my_method does not happen in the test, as if the callback function is not executed in the test. However, since the test does not fail, the method :my_method must have been called during the test.

Why is that? It is because of how receive(:my_method) works. We can think of it like this: receive() replaces the original method :my_method with a new implementation, remembering only that this method was called in the code. But the original implementation of the method :my_method is overwritten in the test and thus not executed.

But what if I want to run the original implementation of the method :my_method?
For this there is and_call_original ( docs Show archive.org snapshot ):

expect_any_instance_of(Movie).to receive(:my_method).and_call_original
create(:movie)  # <-- this is where the method :my_method should be called

This will execute the original implementation (see here Show archive.org snapshot ).

Posted by Tanja to makandra dev (2023-01-24 13:44)