[rspec-users] lots of nil problems!

David Chelimsky dchelimsky at gmail.com
Sat Mar 20 06:42:25 EDT 2010

On Sat, Mar 20, 2010 at 2:28 AM, Patrick J. Collins
<patrick at collinatorstudios.com> wrote:
> 4.  You do .stub! ...........  This is where I get really
> confused.  From the peepcode screencast that I have watched
> several times, he explained that stubbing is the same as
> mocking-- except there is no expectation of what it returns.
> That made sense when he said it, but in all the examples I've
> seen with code (including yours), there is this .and_return at
> the end..  Which as far as I can tell, is an expectation..  I
> mean, you are asking it to return a specific thing-- that is
> an expectation is it not?  Or does expectation really mean
> something else in this context?

.and_xxx is admittedly confusing, as evidenced by your confusion.
These are _not_ expectations, they are merely configuration.

When you say

  foo.stub(:bar).and_return('this value')

you're saying: hey, foo, you might receive the bar() message. If you
do, return "this value".

When you say

  foo.should_receive(:bar).and_return('this value')

you're saying: hey, foo, you _should_ receive the bar() message. If
you do, return "this value". If you don't, raise an ExpectationNotMet

Neither are saying: hey, foo, you should return "this value", and if
you don't, I'll consider it a failure.

There are also and_raise, and_yield, and and_throw methods that
operate similarly. They are instructions to the object that allow you
to control how it behaves so you can set expectations on other objects
as to how they should respond. Make sense?

There is an alternate syntax that I'm using nearly exclusively at this
point, which is to pass a block along with the stub() and
should_receive() messages:

  foo.stub(:bar) { "return value" }
  foo.stub(:bar) { raise SomeError }
  foo.stub(:bar) { yield "value" }
  foo.stub(:bar) { throw :value }
  foo.should_receive(:bar) { "return value" }
  foo.should_receive(:bar) { raise SomeError }
  foo.should_receive(:bar) { yield "value" }
  foo.should_receive(:bar) { throw :value }

As you can see, there is much less API to worry about here. You're
just supplying an implementation.

This approach also works with scoped arguments:

  input = Input.new
  calculator = Calculator.new(input)
  calculator.should_receive(:add).with(1,2) { 3 }
  input.type("1", "+", "2", "Enter")

I've been thinking of deprecating the and_xxx methods in rspec-2. Does
anybody think that's an awful idea?

More information about the rspec-users mailing list