Topic: I expect a method once, but RSpec thinks it's expected twice

I fought RSpec for an hour, but lost. I hope someone here can help. I have written a spec that expects a method once, but once I add and_return(), RSpec thinks I expect the method twice. I don't.

When I write the spec this way, RSpec correctly expects the method once:

describe PostingsController, " when browsing by category, ignoring authorization" do
  before(:each) do
    controller.stub!(:authorize)
  end

  it "should paginate the postings" do
    postings = []
    postings_pages = mock("a paginator")

    Posting.stub!(:find_by_category_name).and_return(postings)
   
    controller.should_receive(:paginate_collection).with(
      :collection => postings, :per_page => 5
    )

    get :browse_by_category, :name => "irrelevant detail"
   
    assigns[:postings].should eql?(postings)
    assigns[:postings_pages].should eql?(postings_pages)
  end
end


But when I write the spec this way, adding and_return() after should_receive, RSpec incorrectly expects the method twice:

describe PostingsController, " when browsing by category, ignoring authorization" do
  before(:each) do
    controller.stub!(:authorize)
  end

  it "should paginate the postings" do
    postings = []
    postings_pages = mock("a paginator")

    Posting.stub!(:find_by_category_name).and_return(postings)
   
    controller.should_receive(:paginate_collection).with(
      :collection => postings, :per_page => 5
    ).and_return(postings_pages, postings)

    get :browse_by_category, :name => "irrelevant detail"
   
    assigns[:postings].should eql?(postings)
    assigns[:postings_pages].should eql?(postings_pages)
  end
end


Any hints? I tried adding once and exactly(1).times, to no avail. I added exactly(5).times, and that worked as expected. It looks like and_return() is adding an expectation. Wha?!

<pause />

Aha! I think I see it. Let me guess: the two return values are a shortcut for "on consecutive calls, return...".

Sure enough, there it is in the docs. So how do I return multiple values in a single invocation? Anyone?

Re: I expect a method once, but RSpec thinks it's expected twice

I tried this, and it worked, but it looks wrong. Notice the extra "[]" in the return values:

    controller.should_receive(:paginate_collection).with(
      :collection => postings, :per_page => 5
    ).and_return([postings_pages, postings])

It seems to me the shortcut syntax is too shortcut-y. I would prefer to write this for "on consecutive calls":

    controller.should_receive(:paginate_collection).with(
      :collection => postings, :per_page => 5
    ).and_return.on_consecutive_calls(postings_pages, postings)

This would be clearer.

Re: I expect a method once, but RSpec thinks it's expected twice

I've struggled with rSpec mocking/stubbing in the past, so I decided to switch to mocha which rSpec is compatible with. So far it has worked well.

Railscasts - Free Ruby on Rails Screencasts

Re: I expect a method once, but RSpec thinks it's expected twice

I've struggled with rSpec mocking/stubbing in the past, so I decided to switch to mocha which rSpec is compatible with. So far it has worked well.

I, too, have used mocha in the past. This is a minor problem, and easily fixed, so I'm not ready to abandon RSpec's built-in test doubles framework just yet. For this one thing it does poorly, it has done all the rest very well. It's good to know I can use mocha if I have to.