Mocks Aren't Stubs by Martin Fowler, is a very comprehensive look at two pairs of issues in testing: state-based verification vs behavior verification, and classical TDD vs Mockist TDD.
If you are new to TDD and/or mocking, this article lays the concerns out quite clearly. Fowler's observations about the implications of each approach ring true from my experience. I find that I am a 'classical' TDD'er, when I do TDD. I prefer to use the actual collaborating objects for testing, and I have a certain disdain for using mocks. I do want to isolate an object for unit testing purposes, but I would rather test it in as realistic a scenario as possible. I would like to see that it plays nicely with its collaborators if it is not too expensive or difficult to do. If I mock the collaborators then I am creating an artificial scenario where real behavior might not get tested.
In Ruby, I am much more inclined to use test doubles for objects because it is so easy to re-implement a method on a class. This makes it easy to return the desired value for the test precondition without writing a bunch of extraneous code.
This ability to mock so easily caused me to use mocks a lot more, which is what led me to my hesitance to use mocks now. Once, I created a stub that was naïve in it's simulation and it slightly misrepresented the contract of the collaborator. The real system didn't execute exactly like the stub and therefore the tests did not cover a problematic interaction that existed in the real collaborator. You could argue that it is not the role of unit tests to show these interaction problems between collaborators, but a genuine interaction is always most desirable because it has a better chance of covering real behavior. It also means I can write fewer acceptance tests... sometimes.
How do your experiences match up with Fowler's and mine?
Posted by Bob Evans at January 26, 2007 10:42 AM
TrackBack URL for this entry:
I agree with Jeff Langr: http://agile2007.org/2004/files/XR5-2.pdf
I sometimes start out using mocks for reasons other than for the reasons Langr considers useful (like mocking out system or environment dependencies). When I do, most of the time, I realize that there are testability flaws in my object design. These testability flaws sometimes point to even larger OO design flaws, especially too much coupling.
Which isn't to say that I have completely stopped using behavior mocks in testing; I view them as a scaffold on the way to green -- which I dismantle on the way to clean.
Posted by: Ken Koster on February 7, 2007 09:48 AM