I have officially crossed over....I am now using Mock Objects in my tests and loving it. After much humming and hawing, and trying to figure out how to write truly effective tests, I decided to give it a go, and so grabbed a copy of Rhino Mocks and started the grueling task of converting some data access code so that I no longer needed a database to run the tests. It took a little bit to get my mind around the new way of thinking, but I have to say it worked great. I'm now able to test my data access routines with complete success, and about a 95% code coverage rate. This is all on top of the fact that I'm using Enterprise Library (for 1.1) for data access and exception handling.
Now, there is a very interesting article from Martin Fowler which is called simply "Mocks aren't Stubs". In this article he is discussing two approaches for dealing with the sort of problem that I had with my data access code. One is to create object stubs within your tests that you can use to feed known values back to your tests. This is not at all a bad approach, and I am using it in some cases in conjunction with my mock objects. The other approach is to use Mock Objects for all of the tricky stuff. He observed an interesting dichotomy between the sort of TDD folks who follow each approach: The folks that use stubs tend to be very results oriented in their testing...That is they are verifying the values of various object after performing an action using the test frameworks Assert calls. This, I think, is most in line with the way TDD is supposed to work. For the Mock Object folks, though, another thing starts to happen. These test gain the ability to verify that specific methods are called in a specific order, and therefore the tests that come from this approach start becoming less results-oriented, and rely more on the method verification from the Mocking framework. He points out these two styles of testing without really saying one is better than the other (he does indicate that he tends to be in the Stub camp, but I think that is a personal choice and level of comfort thing), beyond pointing out that relying on the results of the test tends to be more in line with the pure TDD way of doing things.
Now, I had read this article before I started using mocks within my project. I thought about using stubs throughout, but since I was testing data access code, I would have a lot of methods to implement in my stub objects that wouldn't really be part of what I was testing, so it seemed a large waste of my time. As I started implementing mocks in the tests, I paid attention to how I was testing to see if I was becoming a "Mockist" in the Fowler sense. Overall I would say that I am not, currently, a "Mockist". I'm still overwhelmingly validating the results of calls based on the methods I'm testing, and just using the mocks to feed appropriate values into the classes I'm trying to test. As a matter of fact, I could probably remove the call to _mocks.VerifyAll() at the end of my tests, since I don't really care. I can say, though, that the ability to verify what is being called with what arguments has been extremely useful in my data access testing space. I've basically got objects which are making calls to stored procs on Oracle to do my data work. The DAL is a real simple deal that doesn't have much in the way of smarts, but works well enough for a small project. Because of the fact that I'm making stored proc calls to the database, I can now use the mocks to make sure that when I call the Save() method on my User object (for example), It's calling ExecuteNonQuery() with the proc name of SAVE_USER. I can also verify that all of the input an output parameters are being set correctly, which is a big consideration when adding a property to the data objects. In that way I can know that my Save() method is doing what it is supposed to even though it returns no value. This checking could probably be done by stubbing the EnterpriseLibrary Database and DBCommand objects, and then setting values within my stub object, which I could verify using an Assert call, but that seems like an awful lot of work when I have the option to simply set expectations, and then do a VerifyAll().
I think the Fowler article may be making much of a practice which is not that common among people using mocks in TDD. Or maybe there is a slow creep that happens to the developer after months and years of using mocks in their tests that turn them into Mockists. Personally I find that there is a very broad and comfortable middle ground which allows me more flexibility to express my intent quickly and concisely. And after all, expressing intent is one of the major boons of TDD.