78

The following piece of code works as expected:

Object.any_instance.should_receive(:subscribe)

But when using the new rspec expectation it does not work:

expect(Object.any_instance).to receive(:subscribe)

The error is:

expected: 1 time with any arguments
received: 0 times with any arguments

How can I make this work with expect() to receive?

Calin
  • 6,661
  • 7
  • 49
  • 80

2 Answers2

159

There's now a not very well documented method called expect_any_instance_of that handles the any_instance special case. You should use:

expect_any_instance_of(Object).to receive(:subscribe)

Google expect_any_instance_of for more info.

Peter Alfvin
  • 28,599
  • 8
  • 68
  • 106
  • +1 for "not very well documented". Still the case. http://www.rubydoc.info/gems/rspec-mocks/RSpec/Mocks/ExampleMethods:expect_any_instance_of – johngraham Mar 09 '16 at 01:37
  • I have been using `allow_any_instance_of`. Is it an alias of this method? – rubyprince Feb 20 '17 at 03:54
  • 2
    @rubyprince They're different, with the allow methods stubbing behaviour and expect methods testing for behaviour. For example, `allow(my_obj).to receive(:method_name).and_return(true)` stubs `my_obj.method_name()` so if it's called in the test it simply returns `true`. `expect(my_obj).to receive(:method_name).and_return(true)` doesn't change any behaviour, but sets up a test expectation to fail if `my_obj.method_name()` isn't called later in the test or doesn't return true. – Saigo Aug 24 '17 at 19:11
  • Thanks @Saigo. Makes sense now. – rubyprince Aug 25 '17 at 06:33
  • 3
    This syntax is deprecated. Is there any hints on how to do this in today's syntax? – Igbanam Jan 30 '18 at 21:49
  • It is deprecated because it is not clear what you mean by `expect_any_instance_of ` (especially if you have to test several interactions on the same object VS different object), however I still find this very convenient. (source: some thread in the RSpec forums) – Cyril Duchon-Doris Oct 24 '18 at 12:38
  • For the syntax deprecation, see [@Arreth's answer](https://stackoverflow.com/a/57962004/610351) – Jaffa Apr 30 '21 at 18:17
9

Just a heads up, expect_any_instance_of is now considered deprecated behaviour according to Jon Rowe (key rspec contributor). The suggested alternative is to use the instance_double method to create a mock instance of your class and expect calls to that instance double, as described in that link.

Jon's method is preferred (since it can be used as a generalized test helper method). However if you find that confusing, hopefully this implementation for your example case can help make sense of the intended method:

mock_object = instance_double(Object) # create mock instance
allow(MyModule::MyClass).to receive(:new).and_return(mock_object) # always return this mock instance when constructor is invoked

expect(mock_object).to receive(:subscribe)

Good luck!

Arreth
  • 91
  • 1
  • 2