6. Bad practices that make unit testing hard - lilbond/testable-code GitHub Wiki

  1. 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
  2. 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
  3. 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)
  4. 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