6. Bad practices that make unit testing hard - lilbond/testable-code GitHub Wiki
-
Constructor does REAL work!
- "new" keyword in the constructor
- constructor takes partially initialized object and has to set it up
- violating law of demeter in the constructor
- Creating unneeded 3rd party objects in constructor
- Conditional creating of objects based upon flags
- Moving constructor work into an initialize() method
-
Avoid holders/collaborators
- Pass in the specific object that you need as a parameter instead of a holder of that object.
- Avoid reaching into one object to get another
- Warning signs:
- Having to create mocks that return mocks in tests
- Seeing more than one period(.) in a method chaining where the methods are getters.
- Only talk to your immediate friend
- Leave object location and configuration responsibility to the caller
-
Brittle global state and singletons
- Global state and singletons make the APIs lie about their true dependencies.
- Causes side-effects: When running test suites, global state mutated in one test can cause a subsequent or parallel test to fail unexpectedly.
- Need to call setup() and/or reset() methods for each test
- Common scenario where such practices can be seen:
- Static init blocks instead of Dependency injection.
- Static method calls in a dependent on library (fix: wrap library in an injectable object of your own)
-
Class does too much work
- Summing up what a class does includes the word "and"
- Class has fields that are used in only specific methods
- Fix:
- Identify the individual responsibilities
- Extract each functionality into a separate class
- Use of one class to perform hidden responsibility of mediating between the others