How to say "any_instance" "should_receive" any number of times in RSpec

Solution 1:

Here's a better answer that avoids having to override the :new method:

save_count = 0
<Model>.any_instance.stub(:save) do |arg|
    # The evaluation context is the rspec group instance,
    # arg are the arguments to the function. I can't see a
    # way to get the actual <Model> instance :(
    save_count+=1
end
.... run the test here ...
save_count.should > 0

Seems that the stub method can be attached to any instance w/o the constraint, and the do block can make a count that you can check to assert it was called the right number of times.

Update - new rspec version requires this syntax:

save_count = 0
allow_any_instance_of(Model).to receive(:save) do |arg|
    # The evaluation context is the rspec group instance,
    # arg are the arguments to the function. I can't see a
    # way to get the actual <Model> instance :(
    save_count+=1
end
.... run the test here ...
save_count.should > 0

Solution 2:

There's a new syntax for this:

expect_any_instance_of(Model).to receive(:save).at_least(:once)

Solution 3:

I finally managed to make a test that works for me:

  mutation = FactoryGirl.build(:mutation)
  Mutation.stub(:new).and_return(mutation)
  mutation.should_receive(:save).at_least(:once)

The stub method returns one single instance that receives the save method multiple times. Because it is a single instance i can drop the any_instance method and use the at_least method normally.

Solution 4:

This is Rob's example using RSpec 3.3, which no longer supports Foo.any_instance. I found this useful when in a loop creating objects

# code (simplified version)
array_of_hashes.each { |hash| Model.new(hash).write! }

# spec
it "calls write! for each instance of Model" do 
  call_count = 0
  allow_any_instance_of(Model).to receive(:write!) { call_count += 1 }

  response.process # run the test
  expect(call_count).to eq(2)
end