Mocking is the primary problem with TDD as it exists right now. "Isolated testing" (or isolated TDD) is advocated by people like Uncle Bob. Many developers listen to Uncle Bob and end up believing that unit testing without complete isolation is not "real" unit testing.
Isolated unit testing is supposed to improve your designs. But when you mock everything, you end up with tests that know everything about your implementation (white box testing). The result is that refactoring breaks your tests. Your tests no longer document how to use the system; they are merely a mirror of its implementation.
Kent Beck's central point in his book is that TDD mitigates fear, allows refactoring, and gives you immediate feedback. Extensive mocking makes developers fearful to refactor (thus hurting design) and reduces the quality of feedback. Not to mention it makes your tests hard to refactor too.
Martin Fowler explains the difference between "classical" and "mockist" testing:
I generally agree. I think Uncle Bob has recently realized all his advocating without public explanation causes a lot of confusion. He's been blogging quite a bit this past month, two posts of which are related to mocking:
I really don't get the debate. If you want to test state vs. behavior you still need to orchestrate and verify that state. You're still "mocking" because you're (presumably) not using a production system on which to test and you're using predictable, idempotent tests and test data. The only difference is you're not using a mocking "framework". Seems to me all you're doing is inheriting a lot of external dependencies that have little or nothing to do with your test. I don't see mocking as behavior vs. state, but rather just a way to remove dependencies that lead to brittle tests.
> you still need to orchestrate and verify that state.
Only if you limit yourself to testing using unit tests. Two of the strongest testing tools care not one bit about internal state.
Combinatorial testing tests all possible combinations of input pairs, and looks for the system to fail.
Fuzz testing creates a fairly large volume of noise as input, and looks for the system to fail.
Integration testing should be in your toolbox right alongside unit testing, and will exercise objects which are not appropriate for unit tests.
> inheriting a lot of external dependencies that have little or nothing to do with your test.
I've found that this kind of thinking leads to development practices which rely on unit tests & production as their sole methods of testing. If a component is part of your production system, it should also be part of your test system.
I spent more time building my mocks instead of building my tests. Sometimes a file might have 90% mocks and 10% tests. Or maybe that's just my mocking framework...
An other reason could be it's a main entry point for code execution, a class that only purpose is the glue others.
In that case, having a lot of mocks is a code smell pointing that you should probably test this on the integration level rather than on the unit one (and thus, discard mocks and use "real" everything).
(but beware not to be too much self indulgent on what is a gluing class, most of the time, they are not and it's indeed a god class problem).
It could just be that the module of code under test doesn't do enough. If you need to mock a service, database, other service, error-handler, etc ... but the core logic is just verifying that <some condition> is met, then this is going to be the case.
Personally I like to avoid mocking for cases like this, since integration tests can usually suffice.
As you said, though, it could also be the framework. If you're in C#-land, Moq is pretty terse with the syntax so the actual mocking code isn't that big.
In many cases, isolated testing does not require test doubles. There are alternatives to mocks: as long as the system under test is not manipulating its dependencies, you can get the state you need from the external resources and pass that into your classes.
Isolated unit testing is supposed to improve your designs. But when you mock everything, you end up with tests that know everything about your implementation (white box testing). The result is that refactoring breaks your tests. Your tests no longer document how to use the system; they are merely a mirror of its implementation.
Kent Beck's central point in his book is that TDD mitigates fear, allows refactoring, and gives you immediate feedback. Extensive mocking makes developers fearful to refactor (thus hurting design) and reduces the quality of feedback. Not to mention it makes your tests hard to refactor too.
Martin Fowler explains the difference between "classical" and "mockist" testing:
http://martinfowler.com/articles/mocksArentStubs.html#Classi...