Put simply, writing unit tests help expose flaws in your code.
This spectacular guide to writing testable code, written by Jonathan Wolter, Russ Ruffer, and Miško Hevery, contains numerous examples of how flaws in code inhibit testing. Thus, if you code is testable, it is easier to use. Most of the "morals" are ridiculously simple tips that vastly improve code design (Dependency Injection FTW).
For example: It is very difficult to test if the method computeStuff operates properly when the cache starts evicting stuff. This is because you have to manually add crap to the cache until the "bigCache" is almost full.
public OopsIHardcoded {
Cache cacheOfExpensiveComputations;
OopsIHardcoded() {
this.cacheOfExpensiveComputation = buildBigCache();
}
ExpensiveValue computeStuff() {
//DOES THIS WORK CORRECTLY WHEN CACHE EVICTS DATA?
}
}
However, when we use dependency injection it is far easier to test if the method computeStuff operates properly when the cache starts evicting stuff. All we do is create a test in where we call new HereIUseDI(buildSmallCache()); Notice, we have more nuanced control of the object and it pays dividends immediately.
public HereIUseDI {
Cache cacheOfExpensiveComputations;
HereIUseDI(Cache cache) {
this.cacheOfExpensiveComputation = cache;
}
ExpensiveValue computeStuff() {
//DOES THIS WORK CORRECTLY WHEN CACHE EVICTS DATA?
}
}
Similar benefits can be had when our code requires data that is usually held in a database...just pass in EXACTLY the data you need.