I recently finished up Roy Osherove’s The Art of Unit Testing: with examples in C#. This book is an outstanding introduction to unit testing object-oriented languages, and I highly recommend it. The biggest reason I recommend the book is that it goes well beyond the simplistic “test that 1 + 2 = 3” types of tests. Instead, Osherove creates a simple but functional application and walks through unit testing technique in a realistic application. Instead of testing that math still works or that the underlying framework he’s using does what it promises, Osherove shows the various logic points within his application that need tested and how to do these.
There is a significant amount of work in this book built around how to test brownfield applications, and I appreciate that. Most of the applications we work with were never designed for testability, so Osherove goes through a number of techniques to create “seams” that we can use to test our code, breaking apart tightly-coupled modules and allowing us to inject test code more easily. My favorite of these techniques is extract-and-override, as it is a great gateway for some of the more work-intensive techniques such as introducing inversion of control and interfaces.
Osherove also shows what you should not unit test. Aside from the above examples (seriously, I hate how so many unit test introductions are built around ensuring that simple arithmetic is still correct), the author points out that there are sections of code you can not and should not unit test. These sections of code generally have to do with external data access, and thus are eligible for integration testing but not unit testing.
But even with that in mind, Osherove spends a great deal of time discussing fakes, stubs, and mocks. I like how he differentiates the three. Fakes are artificial code introduced for the purpose of testing, and encompass stubs and mocks (and more). Stubs are artificial code designed to simulate an external service, allowing you to test the calling code. Mocks are similar to stubs, with the major difference being that you don’t assert against stubs. Osherove also provides a rule of thumb that you should only mock one service in a single test; if you try to assert against more than one fake, that’s a clue that your test is trying to do too much.
If you are an object-oriented developer and want to learn more about unit testing, I highly recommend this book. It is not the sum of developer testing, but is a great deep dive to this side of testing.