These days, my default approach for writing tests is to construct the system under test using the builder pattern. Delegating construction of the SUT to a fluent builder has a number of benefits:
- Test code becomes more readable and expressive, encouraging meaningful tests, preventing setup code from drowning out test intention and ultimately providing better documentation of behaviour.
- Reuse of setup code is easier and the cost of adding or changing dependencies and construction logic is dramatically reduced.
- Semantically meaningful test setup encourages good encapsulation in production code (which, in turn, makes changing behaviour by adding and removing components - instead of ripping up tests - much easier).
- Dependencies’ validity can be tested in a single test and “assumed” in others by supplying valid defaults in the builder, further reducing noise in tests.