There's an interesting exchange going on in the .Net world (actually, in the Israeli .Net TDD with Mocks world, which I imagine is about as small as a community gets).
I'm with Osherove on this one. Although some of the rules he's worried about breaking derive from working with legacy languages, rather than one that really is object-oriented, he makes a fundamental point about Test Driven Development. The effort of adjusting your ideas to make them testable will give you better, more flexible code. This allows you to keep up with the changes that arise in any project and is the other half of the contract you sign when you choose incremental development. I'm sure that Lopian feels that his approach is the way to get there.
I'm not a fan of TypeMock, except where you're trying to crack open a legacy codebase. It's a very smart library but, to me, it misses the point of TDD with Mocks, which is to force the programmer to think about the relationships between the objects they're programming. When you override a feature in a class for the purposes of mocking (or, more often, stubbing), you're addressing a dependency between two objects, but you're leaving it implicit. When I come back to the production class, there's nothing there to tell me that it plays this particular role, so I'll have to do the analysis again. That's why I've never been keen on the cglib versions of the java mock libraries. If it's that simple an object and you don't want to introduce an interface, then don't mock, use the real thing.
But, if you have to mock out an object to get the test to work, then that object is an external dependency and should be passed in. Reaching in to an object and manipulating its internals ties the test to the implementation and makes it brittle—which is the usual objection made against interaction testing. In this case, I have to agree.
One more point, Lopian writes,
Have you ever tried to browse a code with loads of interfaces, it take ages because you have to keep finding the concrete implementation, and the place where the instance was created.In my world that's not the case. First, the usual Java IDEs take me very quickly from interface to implementation. Second, in a codebase that uses Dependency Injection well, significant objects are instantiated in just a few places. The place where the instance is created usually turns out also to be where other objects relevant to my task are also created. Then I know that the design is working.
Correction. Oren Eini is the author of Rhino Mocks,