views:

383

answers:

1

In rspec (1.2.9), what is the correct way to specify that an object will receive multiple calls to a method with a different argument each time?

I ask because of this confusing result:

describe Object do

  it "passes, as expected" do
    foo = mock('foo')
    foo.should_receive(:bar).once.ordered.with(1)
    foo.should_receive(:bar).once.ordered.with(2)
    foo.bar(1)
    foo.bar(2)
  end

  it "fails, as expected" do
    foo = mock('foo')
    foo.should_receive(:bar).once.ordered.with(1) # => Mock "foo" expected :bar with (1) once, but received it twice
    foo.should_receive(:bar).once.ordered.with(2)
    foo.bar(1)
    foo.bar(1)
    foo.bar(2)
  end

  it "fails, as expected" do
    foo = mock('foo')
    foo.should_receive(:bar).once.ordered.with(1)
    foo.should_receive(:bar).once.ordered.with(2)
    foo.bar(2) # => Mock "foo" received :bar out of order
    foo.bar(1)
  end

  it "fails, as expected, but with an unexpected message" do
    foo = mock('foo')
    foo.should_receive(:bar).once.ordered.with(1)
    foo.should_receive(:bar).once.ordered.with(2)
    foo.bar(1)
    foo.bar(999) # => Mock "foo" received :bar with unexpected arguments
                 # =>   expected: (1)
                 # =>         got (999)
  end

end

I expected the last failure message to be "expected: (2)", not "expected (1)". Have I used rspec incorrectly?

+1  A: 

Similar to this question. The recommended solution is to call as_null_object to avoid the confusion of messages. So:

describe Object do
  it "fails, as expected, (using null object)" do
    foo = mock('foo').as_null_object
    foo.should_receive(:bar).once.ordered.with(1)
    foo.should_receive(:bar).once.ordered.with(2)
    foo.bar(1)
    foo.bar(999) # => Mock "foo" expected :bar with (2) once, but received it 0 times
  end
end

The output is not the same as your second case (i.e. "expected 2 but got 999"), but it does show that the expectation was not met.

zetetic
That's better: it changes the error message from the erroneous "Expected (1) got (999)" to "expected :bar with (2) once, but received it 0 times." Not exactly to the point, but at least it's not a flat-out lie like what I was getting. But now it fails to detect: foo.bar(1); foo.bar(999); foo.bar(2). It seems as though one has to trade away the ability to detect some errors in order to get a more truthful error message. Not your fault, I know.
Wayne Conrad