I wanted to talk a little bit today about some things I am discovering about the test-driven development practice in regard to mock objects. I honestly believe that mock object's have their best application at a system's context boundary, and that only if you have no other option. My thinking is still forming in this area, and, as I have proven in the past in areas like this, I may entirely change my mind as more information becomes available.
The basis for my desire to only use mock objects in a limited way has to do with noise in tests that I believe is being caused by the introduction of mock objects. By "noise", I mean code that distracts the mind from clearly understanding its intent. It is not that mock objects cause noise in the production code, it is the test code that is my concern.
In my practice, I have found that when I make heavy use of mocks to write some code and then come back to that code months later, I have a much harder time remembering what I was doing with the code, than with code that used "stubs" instead.
I have attempted to analyze this problem for possible explainations and I believe that the primary "noise" is caused by a natural focus on talk, rather than results. It is as if I am listening to conversation that is only a means of solving a problem, rather than an end, which represents an actual solution. It seems to be the norm, in my experience, that these conversations between objects do not describe the end result well at all. I find that I must carefully reflect on the meaning of the sum of the conversations in order to understand the purpose of the unit under test.
When stubs and emulators are used, I find that a very natural communication about the meaning of the software results. One of the leading arguments that I believed earlier in favor of using mock objects was that it reduced the need to change the software for testability. I have found in practice, however, that this is mostly true at a context boundary. In practice the whole argument for not changing code just to make it more testable has fallen from favor. I now believe that that making code more testable usually creates a stronger form of the software that is easier to understand rather than more difficult.
This does not mean that the software is easeir to write, however. I have found in practice that it is actually harder to write testable code without mock objects. But the fact that the resulting code is much easier to read and maintain when designed with testability in mind is a strong argument in its favor.