[rspec-users] Mock and Stub objects

David Chelimsky dchelimsky at gmail.com
Thu Jun 11 12:56:48 EDT 2009


On Thu, Jun 11, 2009 at 11:36 AM, Stephen Eley<sfeley at gmail.com> wrote:
> (NOTE: This reply is no longer really for Amit's benefit any more.
> What David said made perfect sense as an answer to the original
> question.  Now I'm just spinning off into theory.)
>
> ((But David -- if the repetition of this whole argument
>
> On Thu, Jun 11, 2009 at 9:36 AM, David Chelimsky<dchelimsky at gmail.com> wrote:
>>
>> Steve wrote in his reply earlier in this thread that we don't want out
>> controller specs failing because the model is broken. But it's not
>> just when the model breaks. It's when the model *changes*.
>
> True.  Though if I wanted to play Devil's Advocate, I could make a
> case that from the point of view of the controller, it's the same
> thing.  "What?  The Widget wants WHAT now?  Hey, I know all about
> widgets, and this widget's not doing what I expect any more.  Must be
> something wrong with it."
>
> (Of course, that exact attitude points to a lot of what's wrong in
> human relationships, not just OO ones.  >8->  So I wouldn't defend
> that case rigorously.  Still -- it's a problem that can be exacerbated
> by the sort of static expectation mocks play into.)
>
>
>> That fails, so we add "validates_presence_of :date" to the model and
>> then the spec passes. Success! Except now the valid attributes case in
>> the controller spec fails because we've changed the meaning of valid
>> for this model. So you have to go back and change this and every other
>> example that creates a Widget without a date.
>
> Yep.  But isn't the difference just a matter of timing?  If you just
> added a new requirement to Widgets, the controller *needs* to change
> before you hit production or it's going to break in real-world use.

This may be true in some cases, but generally with validations the
controller passes the params straight through to the model without
caring about them in any way. In those cases, where the controller is
only interacting with methods that are part of AR::Base, you're not
really risking a validation change effecting the controller's
behaviour.

> You'll eventually have to go back and change every mock, and _then_
> change every example anyway.  If you don't, then the mocks no longer
> represent the true expectation of a Widget and your controller's
> behavior is no longer correct from the widget's POV.  You end up with
> specs that pass when the application wouldn't.

I think you're generalizing here, which is what I was driving at with
my point about knowing when to use stubs/mocks and when not to. As I
mentioned above, these changes need not always propagate up to the
controller or its specs. I would agree with you that there is
additional risk in cases where the changes to the model actually do
require changes to the controller. Though I mitigate that risk by
working with Cucumber first, which catches those sorts of
mis-alignments a bit later than if I wasn't using stubs/mocks, but
certainly before those changes make it to production.

At the moment, one of my projects does not use Cucumber. We're using
RSpec for both higher level and lower level specs. In this case, the
level of use of stubs/mocks is far lower than in other projects I've
worked on.

> As a matter of practicality, I think I would *prefer* the controller
> spec to fail right away so that I don't forget to update my mocks
> later on.  Yes, I *should* have integration tests that would catch
> this, so I ought to be safe if I'm doing other things right; but if
> the controller spec will have to change sooner or later, I'd rather it
> bugged me to change it sooner.

I can appreciate that, though it's not how I operate.

> As I see it, the cost of violating DRY and repeating the expectations
> of a Widget in a number of mocks, which then have to be maintained
> separately, is *usually* higher than the cost of referring to the
> actual model, with slower test runs and less specific failure
> pinpointing.

I run the specs after every change (using autospec). For this to work
effectively, the specs need to run fast. This is one of the benefits,
in my view, of having two separate tools for dealing at different
views of the code (i.e. RSpec and Cucumber).

>  I don't see earlier spec repair as a cost at all, given
> that those specs will have to change anyway.  There may be cases where
> this would pay off to me, but the typical highly coupled Rails
> model/controller relationship isn't it.  In practice I only use mocks
> these days to take the place of outside interfaces or bigger, more
> conceptually distinct subapplications.
>
>
>> [ . . . ]   Really, I think
>> that's what we should all be striving for. Not so much "should I use
>> mocks or not," but "when should I choose to use them?"
>
> And here...  Here you made me really pause and think.
>
> Enough to make it a separate message.

Looking forward to it.

Cheers,
David

>
>
>
> --
> Have Fun,
>   Steve Eley (sfeley at gmail.com)
>   ESCAPE POD - The Science Fiction Podcast Magazine
>   http://www.escapepod.org
> _______________________________________________
> rspec-users mailing list
> rspec-users at rubyforge.org
> http://rubyforge.org/mailman/listinfo/rspec-users
>


More information about the rspec-users mailing list