Saturday, February 15, 2014

Book Review: Test-Driven Development with Mockito

Test-Driven Development with Mockito provides a general introduction to test-driven development (TDD) before looking at application of Mockito to implement test doubles as part of test-driven development. Test-Driven Development with Mockito is written by Sujoy Acharya, is published by Packt Publishing with a publication date of November 2013, and has about 150 substantive pages of substantive content divided into 9 chapters and 2 appendices. The subtitle of Test-Driven Development with Mockito is "Learn how to apply Test-Driven Development and the Mockito framework in real life projects, using realistic, hands-on examples."

Preface

Test-Driven Development with Mockito's Preface opens with a very brief description of test-driven development and how Mockito plays a role in test-driven development. The preface summarizes each chapter and appendix before recommending what a reader of that book should use while reading the book: J2SE 5, the Eclipse IDE (Kepler 4.3 recommended), and Mockito.

One of the most important parts of a Packt Publishing Preface is the section on "Who this book is for." In this case, the paragraph in this section states:

This book is for developers who want to develop software according to Test Driven Development using Mockito and to leverage various Mockito features. Developers don't need prior knowledge of TDD, Mockito, or JUnit. It is ideal for developers who have some experience in Java application development as well as some basic knowledge of unit testing, but it covers the basic fundamentals of TDD and JUnit testing to get you acquainted with these concepts before you use them.

Chapter 1: Getting Familiar with TDD

As the Preface stated, Test-Driven Development with Mockito does cover "basic fundamentals of TDD" and begins this in the first chapter. This chapter starts out at a very basic level, defining a test in Java development and listing some "available code-driven unit-testing frameworks for Java." In this chapter, we learn that JUnit 4.0 will be used in examples in the book. An example is then presented using Eclipse and JUnit in which the test class is written before the production class. This transitions into more details on the historical background of TDD and lists benefits of TDD.

Chapter 1 continues by looking into how TDD fits into overall software development and how refactoring plays a role in test-driven development. In many ways this first chapter is what you'd expect from a book on test-driven development. The code-based examples of test-driven development do a nice job of illustrating basic techniques and advantages associated with test-driven development. However, there seemed to be some things that seemed a bit out of place in this chapter. In particular, the chapter's extremely brief coverage of "Object-function programming languages such as Scala and Groovy" seemed irrelevant to the rest of the chapter and added little value. As with most books on TDD, this chapter of this book had a paragraph that seemed a bit preachy.

Chapter 2: Refactoring – Roll the Dice

The second chapter of Test-Driven Development with Mockito, as its name implies, focuses on refactoring. The chapter begins by reviewing benefits of refactoring and then discusses "trigger points for refactoring" and when not to refactor. Some relatively lengthy code listings are provided to show some code in desperate need of refactoring with text explaining issues with the code and possible ways to refactor that code. This section of the book also introduces the Eclipse plugin CodePro Analytix.

The second chapter moves onto coverage of code smells. Duplicate code with switch statements is shown as a code smell and there is discussion and more code listings on how to refactor this using the strategy pattern and polymorphic behavior. Other code smells that are covered in this chapter along with potential remedies include duplicate code, comments, long methods, long method parameter lists, large classes, dead code, and overengineering.

This second chapter is a reasonable introduction to code smells and how to use refactoring and other techniques to deal with them. This chapter mentions common object-oriented and software development principles such as YAGNI, DRY, open-closed principle, and strategy pattern. A single chapter of a book cannot compete with an entire seminal treatment of a subject, but this chapter does provide a good illustration of how refactoring fits into TDD.

Chapter 3: Applying TDD

The third chapter of Test-Driven Development with Mockito begins with a bold statement, "Test-Driven Development (TDD) is the new way of programming." The chapter then outlines the simple steps that are taken to implement TDD and is the first chapter in the book to really dive into TDD. The chapter concludes with a lengthy example including code listings and Eclipse screen snapshots to demonstrate JUnit and TDD in practice.

Chapter 4: Understanding the Difference between Inside-out and Outside-in

Chapter 4 of Test-Driven Development with Mockito compares and contrasts TDD's two "common" styles: Outside-In and Inside-Out. The chapter provides details regarding the outside-in approach before listing advantages and disadvantages of that outside-in approach. The same is then done for inside-out, though the coverage is much shorter than for outside-in.

Chapter 5: Test Doubles

Test-Driven Development with Mockito's fifth chapter covers test doubles. The chapter very briefly discusses why test doubles are useful (I don't think this part is particularly strong) before categorizing the types of test doubles (dummy, stub, mock, and fake). The coverage of these types of test doubles is much better than the general introduction to test doubles and provides nice code examples and discussion on each and how they are different.

Chapter 6: Mockito Magic

Chapter 6 of Test-Driven Development with Mockito is the book's first significant look at Mockito (although Mockito was mentioned in Chapter 5 for the example of the mock category of test double). The chapter begins with an overview of Mockito and explains Mockito's primary roles in test-driven development: "Mockito plays a key role to mock out external dependencies" and helps achieve the desired "qualities of unit testing."

Chapter 6 continues by demonstrating adding Mockito to Eclipse. There are numerous screen snapshots of Mockito being used within Eclipse (these are in color in the electronic edition of the book). The chapter introduces key annotations and functionality provided by Mockito and demonstrates using Mockito to address things commonly tested using mocks. A reader of this book who's primary interest in the book is learning Mockito would find this to be one of his or her favorite chapters of the book.

Chapter 7: Leveraging the Mockito Framework in TDD

Test-Driven Development with Mockito's seventh chapter begins with a brief discussion of classical TDD versus mockist TDD. The chapter is then introduced with the statement that it will "use Mockist TDD style to mock external dependencies and explore Test-Driven Development." The entire chapter is then devoted to a fairly realistic example of building an "online portal for the aspiring game developers" with test-driven development techniques and using Mockito to mock out the external interfaces.

Chapter 8: World of Patterns

Chapter 8 of Test-Driven Development with Mockito opens with reference to Robert Martin's "three important characteristics of a bad design": rigidity, fragility, and immobility. The chapter then covers "higher level design guidelines" of modularity, high cohesion, and low coupling and "lower level design principles" of Open/Closed Principle, Dependency Inversion Principle, Integration Segregation Principle, Single Responsibility Principle, Liskov Substitution Principle, and the Law of Demeter.

The next section of Chapter 8 discusses design patterns. The section provides an overview of what design patterns are, how they are categorized, and provides a couple of examples of applying design patterns.

Chapter 9: TDD, Legacy Code, and Mockito

The ninth chapter of Test-Driven Development with Mockito discusses what constitutes legacy code and then emphasizes: "Any code with no unit test is legacy code." Chapter 9 looks at some common less-than-testable features of legacy code and how to refactor that code for greater testability. The chapter then moves onto how Mockito can make it easier to refactor code to be more testable.

Appendix A: TDD Tools and Frameworks

Appendix A covers Eclipse IDE and JUnit 4 unit testing framework. It discusses using keyboard shortcuts in Eclipse (including "The mother of all shortcuts is Ctrl + Shift + L" to see all shortcuts) and emphasizes those shortcuts useful in refactoring and TDD. There are some nice color screen snapshots showing shortcuts applied in this section. Appendix A's coverage of JUnit begins with the statement, "Inheritance in Java is not a smart thing to implement" to explain advantages of JUnit 4.x (which supports annotations) over earlier versions which required inheritance. Appendix A's coverage of JUnit covers fundamentals of JUnit and demonstrates using Eclipse shortcuts in JUnit unit test development.

Appendix B: Agile Practices

Appendix B discusses continuous integration (CI) in general before covering Jenkins as a particular continuous integration tool. The author begins continuous integration coverage with the statement, "In a good software development team, we'd find TDD as well as CI." There are numerous color screen snapshots depicting configuration of Jenkins. Appendix B also discusses the "Agile development methodologies Scrum and Kanban." After briefly discussing Agile in general and providing a reference to the Agile Manifesto, Appendix B focuses on Scrum and Kanban specifically.

General Observations
  • Test-Driven Development with Mockito attempts to cover numerous topics within its roughly 150 pages.
  • Test-Driven Development with Mockito has several nice images. I especially like the screen snapshots that depict Eclise refactoring keyboard shortcuts and the screen snapshots that depict Jenkins configuration. An advantage of my reviewing the PDF provided by Packt Publishing is that these images are in full color.
  • The code listings are useful in illustrating the points being made, but the lack of color syntax (even in the electronic PDF version) make it more difficult to read the code quickly and easily. I have become spoiled by my IDE (and even my vim!) and online code listings featuring color syntax. Reading code without color syntax reminds me of the "old days," but the nostalgia is not worth the extra effort required to read the code.
  • Test-Driven Development with Mockito has some typos in it and also has some awkward and incomplete sentences. However, none of these were significant enough to prevent me from picking up the concept being covered.
  • Although the flow of topics covered in Test-Driven Development with Mockito generally made sense, there were some aspects of the arrangement of the various concepts that were a bit awkward. In particular, there were a couple concepts that were presented in almost a "side note" manner at first and were not very clearly explained, but then were much more clearly explained in the later sections that focused on that topic.
  • As is the case with just about every TDD-related book I have read, Test-Driven Development with Mockito is a highly opinionated book. Although I generally agreed with most of the opinions, I felt some of the stated opinions were backed up better than others and some I don't feel quite as strongly about or think are quite as certain as the author does. That being stated, I do like to see opinions expressed and I generally agreed with them in principle. The more focused books I mentioned in an earlier bullet would be useful for the reader of Test-Driven Development with Mockito who wanted to better understand the "why" behind some of the opinions expressed in this book.
Conclusion and Recommendation

Test-Driven Development with Mockito will be most beneficial to readers who have little to no familiarity with the numerous concepts introduced in the book (test-driven development, refactoring, object design, JUnit, Mockito, etc.). The book provides an overview of each of these and how they are used together. Developers who have read other books on these subjects may not find the introductory information in Test-Driven Development with Mockito as useful or as new to them. Developers wanting in-depth coverage of a topic might prefer a book focused on that particular topic. The book is most useful for those using the Eclipse IDE, but many of the sections are useful for developers who don't use Eclipse.

No comments: