Test Driven Development is the in-thing and Mock objects play a key role in it. But there are many variants of so called Mock objects which are loosely called Mock’s as Martin points out in his article.
Your approach to testing depends on your philosophy behind SDLC. The kind of Test Double ( a generic term of any object that replaces a collaborator) you would use in a project depends on which philosophy you subscribe to.
You Philosophy shapes way testing and design play together, which Martin terms as the classical and mockist styles of Test Driven Development. The key difference between the two approaches is how test results are verified: a distinction between state verification and behavior verification.
The classical testers subscribe to the inside-out approach, where you would design/test the core modules first and work on the dependent or outer layer components next. In this approach, UI will be the last one to be built. This would be conducive to using real collaborators. Classics do use Test Stubs when using a real collaborator becomes awkward.The classic’s are concerned about the state of the Test Stub at the end of the test.
The mockist on the other had take a out-side-in approach, where they will build the UI first and mock all the collaborators. Mockis’s achieve this goal by injecting the desired behavior into the mock objects and verify if the behavior at the end of the test.
Both approaches have their place, but here are few significant differences.
Classic TDD :
Classic TDD takes a inside-out approach, building one feature at a time. In this style you take a feature and decide what you need in the domain for this feature to work. You get the domain objects to do what you need and once they are working you layer the UI on top. Doing this you might never need to fake anything. A lot of people like this because it focuses attention on the domain model first, which helps keep domain logic from leaking into the UI.
Tests can share common Fixtures and there is no need to setup the behavior each time.l
If the tests involve multiple collaborators, it might be difficult to achieve defect localization.
Bugs introduced in data or modules can cause multiple tests to fail, hence increasing the possibility of ” fragile tests”
Re-factoring code in one module can impact multiple tests
Mockist’s TDD :
“Defect Localization” is easy with mocks, as the only object that’s real in a test is the SUT ( system under test)
“Fragile Tests” are under control a data/logic interference is highly limited
Re-factoring code doesn’t impact multiple tests, as the changes are localized to tests.
Test Fixtures cannot be shared , as the behavior needs to be built into the mocks for each test, which can get tedious.
The out-side-in approach tends to be counter intuitive to a agile practitioner. As the focus is on building the story and flows first and developing the individual components later.