I have been applying Test-Driven Development for quite some time, and I think it provides an excellent foundation for creating quality code.
But one thing has always been bothering me, handling sub-systems correctly.
Let me explain with an example.
Methods with a return value
If I have a method without any direct dependencies like below. It is easy to write a test for it. The production code is self-contained with no dependencies.
The return value is all I care to assert. Easy!
Methods that pass requests to a subsystem
But if I have a method whose responsibility is to pass the request on to a subsystem, I have to mock the sub-system to know if the code is correct.
It can’t be asserted from the return value alone.
Consider this example; we need to know if the mapping from the controller to the service is correct. To do that, a mock of the UserService is needed.
I like the first example because I can test what I need without knowing anything about the implementation.
But the second example has always given me a cringe feeling because it binds my test to the implementation details.
Different schools of thought
Then I discovered that the two examples correspond to two different schools of thought: the first called inside-out and the second outside-in.
Inside-out focuses on testing behavior and avoiding dependencies.
Outside-in makes heavy use of mocks to test the implementation.
None of the approaches are wrong. They just have a different focus.
Have you come across difficulties with TDD? Hit reply and let me know.