[rspec-users] Surprising mock behavior

Stephen Eley sfeley at gmail.com
Sat Oct 18 22:51:57 EDT 2008

On Sat, Oct 18, 2008 at 9:49 PM, Mark Thomson <mark.thomson at ieee.org> wrote:
> [...]  What I've observed is that it behaves differently
> if I include a "should_not_receive('...')" expectation somewhere in the
> spec. In that case it seems that I can have as many "file.puts()" in the
> component being tested as I like without specifying expectations for them,
> and they pass just fine.

Hmm, that does seem weird.  Without seeing your actual code I think
it'd be difficult for anyone to say if it's a bug, or expected
behavior with unexpected results, or something else causing the issue,
etc.  It _smells_ like a bug to me the way you describe it --
specifying messages you shouldn't get ought not change the expectation
of messages you _do_ get -- but then, I've often been flummoxed by
test behavior in my own code when it was really my misunderstanding
causing the problem.  Maybe file a Lighthouse ticket with code samples
clearly showing failing and passing tests.

> That aside, I also can't help questioning the way the "should_receive"
> expectation is expressed. Maybe specifying every message sent to the mock is
> absolutely the right way to test the component. But in view of the general
> philosophy of expressing expectations in a way that reflects what they
> actually mean, in my mind this doesn't quite hit the mark.  [ . . . ]

I think the difference in perspective here is that you're focusing in
very closely on the individual "should_receive" calls.  That's not the
level at which this expectation is set.  It's not the presence of a
single should_receive that makes the mock want to know about every
message it gets.  It's the fact that *it's a mock.*  Unless you tell
them otherwise, that's just the way mocks work.  If you don't want to
have to specify everything, then that's what stubs are for.

> In view of this, I wonder if a better way to formulate this test
> might be to say something like -
> object.should_receive :method => :method_name, :with_each_of => [arg1,
> arg2,... argN]

That's not a bad idea, but I suspect your tests in which you're
calling 'puts' over and over might be a bit of an edge case.  Most
spec examples are much simpler, and I suspect it's uncommon to have a
need to call a given method more than once in a single example.  Even
if you're testing an iteration, you don't have to use a _large_ loop
in a test case.  One or two iterations and logical induction ought to
suffice to prove that it works.

Have Fun,
   Steve Eley (sfeley at gmail.com)
   ESCAPE POD - The Science Fiction Podcast Magazine

More information about the rspec-users mailing list