Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rspec - combine expect_any_instance_of and a receive counts

I need to verify that any instance of my class receives a certain method, but I don't care if many instances receive it (they're supposed to).

I tried like this:

expect_any_instance_of(MyClass).to receive(:my_method).at_least(:once)

But apparently, it only allows for a single instance to receive the method multiple times, but not for different instances.

Is there a way to achieve that?

like image 562
Mat Avatar asked Feb 10 '16 16:02

Mat


2 Answers

If you need to live with the code smell, this rspec-mocks Github issue suggests a solution along these lines:

receive_count = 0
allow_any_instance_of(MyClass).to receive(:my_method) { receive_count += 1 }

# Code to test here.

expect(receive_count).to be > 0
like image 155
Gabriel Deal Avatar answered Oct 13 '22 19:10

Gabriel Deal


This is a known issue in rspec-mocks. From the v3.4 documentation on Any instance:

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 a specific instance is expected to receive name twice, or if two receives total are expected. (It's the former.)

Furthermore

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.

Do you have any way to refactor your test or app code to avoid the "confusing edge case"? Perhaps by constructing a test double and expecting it to receive messages?

like image 11
messanjah Avatar answered Oct 13 '22 20:10

messanjah