33
votes

In my Rails controller, I'm creating multiple instances of the same model class. I want to add some RSpec expectations so I can test that it is creating the correct number with the correct parameters. So, here's what I have in my spec:

Bandmate.should_receive(:create).with(:band_id => @band.id, :user_id => @user.id, :position_id => 1, :is_leader => true)
Bandmate.should_receive(:create).with(:band_id => @band.id, :user_id => "2222", :position_id => 2)
Bandmate.should_receive(:create).with(:band_id => @band.id, :user_id => "3333", :position_id => 3)
Bandmate.should_receive(:create).with(:band_id => @band.id, :user_id => "4444", :position_id => 4)

This is causing problems because it seems that the Bandmate class can only have 1 "should_receive" expectation set on it. So, when I run the example, I get the following error:

Spec::Mocks::MockExpectationError in 'BandsController should create all the bandmates when created'
Mock 'Class' expected :create with ({:band_id=>1014, :user_id=>999, :position_id=>1, :is_leader=>true}) but received it with ({:band_id=>1014, :user_id=>"2222", :position_id=>"2"})

Those are the correct parameters for the second call to create, but RSpec is testing against the wrong parameters.

Does anyone know how I can set up my should_receive expectations to allow multiple different calls?

2
That should work. What version of RSpec are you using? Try calling the stubed methods in sequence from the spec (Bandmate.create(...:user_id => @user.id...); Bandmate.create(...:user_id => "2222"...); ...) and see if it works.Rômulo Ceccon

2 Answers

40
votes

Multiple expectations are not a problem at all. What you're running into are ordering problems, given your specific args on unordered expectations. Check this page for details on ordering expectations.

The short story is that you should add .ordered to the end of each of your expectations.

-3
votes

Mock Receive Counts

my_mock.should_receive(:sym).once
my_mock.should_receive(:sym).twice
my_mock.should_receive(:sym).exactly(n).times
my_mock.should_receive(:sym).at_least(:once)
my_mock.should_receive(:sym).at_least(:twice)
my_mock.should_receive(:sym).at_least(n).times
my_mock.should_receive(:sym).at_most(:once)
my_mock.should_receive(:sym).at_most(:twice)
my_mock.should_receive(:sym).at_most(n).times
my_mock.should_receive(:sym).any_number_of_times

Works for rspec 2.5 too.