(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 C.[email protected]
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.
–
Have Fun,
Steve E. ([email protected])
ESCAPE POD - The Science Fiction Podcast Magazine
http://www.escapepod.org