[rspec-users] Mock and Stub objects
sfeley at gmail.com
Thu Jun 11 12:36:49 EDT 2009
(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.
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.
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.
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 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.
Steve Eley (sfeley at gmail.com)
ESCAPE POD - The Science Fiction Podcast Magazine
More information about the rspec-users