Originally developed by Kent Beck and Eric Gamma for its use in extreme programming [1], JUnit is an automated unit-testing framework for the Java programming language. In fact, it is just an instance of the xUnit testing framework family. Albeit typically associated with test-driven development [2], xUnit can be extremely helpful whether you write code test first or not, since automated unit tests provide an invaluable safety net for relentless refactoring, apart from their use as code documentation or even “executable specification.” As Martin Fowler wrote, “never in the field of software engineering has so much been owed by so many to so few lines of code.” I heartily agree with him.
Meszaros has written a hefty book on the effective use of xUnit. At nearly 900 pages, it covers almost anything you could ever want to know about xUnit tools and the design rationale behind them, but almost nothing about test-driven development. Some excellent books have already covered that topic [2], but none in enough depth to work out the inner workings and proper usage of xUnit.
The book is organized into three parts, following the series’ approach [3]. The first 180 pages of the book, “The Narratives,” provide a tutorial on effective test automation using xUnit. Later, a 450-page pattern catalog details test strategies, usage patterns, and code idioms associated with xUnit usage. In between these two, the part titled “The Test Smells” describes symptoms that usually indicate some kind of problem in your test code.
“The Narratives” delimit the book’s scope, introduce some terminology, and basically deal with the goals, philosophy, principles, and strategies used in modern test automation. They describe some xUnit basics, such as the “setup, exercise, verify, and teardown” test execution cycle. Finally, they also address how to test indirect inputs and outputs, by means of “test doubles,” and Meszaros gives some advice on testing with databases. In general, this part of the book provides an excellent overview of test automation. However, I did not particularly like the frequent use of forward references to patterns yet to be discussed. In my opinion, that organization is better suited to a Web page than to a technical book, especially if it is intended to be read by software developers who might not be already acquainted with xUnit test automation.
The second part of the book, just as in the book by Fowler et al. on refactoring [4], deals with “smells.” In other words, it describes symptoms of problems in test code. Although the problems are not necessarily stated, Meszaros thoroughly analyzes their potential impact, probable causes, and potential solutions. You have probably experienced some smells yourself, and you will recognize them as you plunge into Meszaros’ lighthearted vocabulary. This is the shorter but more enjoyable part of the book, where you will find recommendations on making obscure tests more readable, avoiding fragile tests due to interface sensitivity, and not playing “assertion roulette” to figure out who the “mystery guest” is (a slightly improved version of printf debugging).
The third part of the book, intended as a reference, contains a detailed pattern catalog. Each pattern description follows a practical format that includes “How It Works” and “When to Use It” sections, some implementation and refactoring notes, and code examples (mostly written in Java, but also in C#, Ruby, and C++). This catalog blends xUnit usage patterns with sound design principles and information that you might only need if you decide to port xUnit to new programming platforms. I particularly liked the patterns devoted to test doubles and design-for-testability techniques. Meszaros discusses usage and construction issues for test stubs, test spies, mock objects, and fake objects. He also addresses the use of dependency injection, dependency lookup, test-specific subclasses, humble objects, and test hooks as “the last resort.”
Meszaros promotes the effective use of xUnit frameworks for making unit tests more maintainable just by applying the same design principles you would apply to production code. His (painstaking) thoroughness, however, makes this book lengthier and more verbose than necessary, and stand-alone pattern descriptions become somewhat repetitive. Even though its comparison, in the foreword, with the landmark Gang of Four book [5] seems a bit of a stretch, it must be acknowledged that this book is a good reference for developers interested in xUnit tools. The problem is that beginners should probably start somewhere else [2], while much of the material will seem too obvious to experienced xUnit users. Meszaros’ advice is sound, and you will also find valuable comments on dealing with legacy code, although better alternatives exist for that, also [6].