This article brainstorms how design choices for better code testability fits into the big picture of providing a continuous stream of business value to the customer. Exploring the possible software design options even before the coding starts enables decoupling and dependency injection which makes the software all the more robust and flexible to absorb future changes in the customer requirements.
What is a unit? A unit is the smallest testable part of an application. Unit tests are written from the specification (FSD/TDD) based on how the product would be used by the end customer. It should be tested in isolation without any dependency. All the dependencies should be mocked up using stubs so that the unit tests are simple and fast. These tests are supposed to focus only on a specific action without any coding for the dependencies.
For example, the coder develops a method called validate_zip_code. When I enter zip code as 00000 it should return false. This is a unit test. As per the requirement spec, on the shipping form if the customer enters invalid zip code he should be re-directed to the help page that explains what is a zip code. Imagine that this help page is yet to be developed by a different team called consumer team. Testing both the zip code field and the display of help page is not unit testing but functional/integration testing. This dependency on the help page display needs to be separated from the validation of zip code. This separation is called dependency injection and it decouples the code making it more robust. The dependencies could be mocked using tools like mockito or easymock. Thus the coder needs to create a mockup or a simulator to substitute for the dependency.
Why dependency injection can ease unit tests? With dependency injection writing unit tests becomes easy and the execution of unit tests becomes simple and fast. This is because the coders are not required to write test code for dependencies as well. Writing code for dependencies makes unit tests complicated and it is also unnecessary since we are not going to do any functional testing with it.
Advantages of Dependency Injection:
1. Unit testing before coding adopts Test Driven Development. The coders can brainstorm the possible execution paths and corner cases that he had never thought of before. This results in a higher quality code
2. Code with lots of dependencies violates the Law of Demeter or the Hollywood principle. With dependency injection the code becomes loosely coupled
3. Determines if the code is fit for testing and increases the testability of the code