Tuesday, January 6, 2015

Book Review: Mockito Essentials

The subtitle of Sujoy Acharya's Mockito Essentials (Packt Publishing, October 2014) is: "A practical guide to get you up and running with unit testing using Mockito." The Preface and seven chapters in Mockito Essentials span approximately 190 substantive pages.

Preface

In the Preface, author Sujoy Acharya writes that Mockito Essentials "is an advanced-level guide that will help software developers to get complete expertise in unit testing using Mockito as the mocking framework." This Preface contains short summaries (typically two or three sentences) of each of the book's seven chapters.

The Preface's section "What you need for this book" lists the software needed to run examples provided in Mockito Essentials and provides links to the versions used in the book (referenced as "latest" at time of writing for some of these). These products include Mockito, JDK 7 or higher, and Eclipse (Luna 4.4.1). I would add that one also needs JUnit for most/all of the examples, PowerMock for some of the examples, and Java EE servlet JARs for some of the examples.

I quote the entire section "Who this book is for" from Mockito Essentials's Preface here because this provides a good idea of expectation of the reader and who the book in written to:

This book is for advanced to novice level software testers/developers using Mockito in the JUnit framework, with a reasonable knowledge level and understanding of unit testing elements and applications. It is ideal for developers who have some experience in Java application development as well as some basic knowledge of JUnit testing, but it covers the basic fundamentals of JUnit testing and the Mockito framework to get you acquainted with these concepts before using them.

Mockito Essentials's Preface also states that a PDF can be downloaded with versions of the book's graphics in color. I downloaded this PDF from the provided link and verified that most of the images are in color. I was also happy to see the the PDF version of the book that I reviewed already had these graphics in color. For those with printed copies of the book, however, this separate PDF with colored graphics could be helpful.

Chapter 1: Exploring Test Doubles

Mockito Essential's initial chapter, for the most part, does not cover Mockito specifically other than referencing when general unit testing practices and concepts are implemented by Mockito. Instead, the first chapter provides an overview of unit testing in general. The chapter begins with a look at why unit testing is valuable and identifies the characteristics commonly associated with effective unit tests. This short section is useful for those new to unit testing, but could probably be skipped for those familiar with unit testing concepts.

The next major section of the first chapter is "Understanding test doubles" and it's much lengthier than the first section on unit testing advantages and effective unit testing characteristics. This second section provides code listings and text explanations of the types of test doubles (term coined in XUnit Test Patterns) described in the chapter: dummy objects, stubs, spies, mock objects, and fake objects.

Chapter 2: Socializing with Mockito

Because the initial chapter of Mockito Essentials is about generic unit testing, Chapter 2 is the first chapter of the book to focus on Mockito. The chapter begins by providing links to both the Mockito main page and Wiki on github and describing Mockito and its open source (MIT) license.

Chapter 2's section on "Exploring unit test qualities" looks at "principles for readability, flexibility, and maintainability" in unit tests. Some of this content repeats ideas from the first chapter, but it's a quick section. The section "Realizing the significance of Mockito" discusses how Mockito addresses "testing-unfriendly behaviors" and interactions "with testing-unfriendly external objects" by mocking those things so the unit tests don't have to be hampered by them.

The "Working with Mockito" section of Chapter 2 starts off by displaying the Mockito logo (in color in PDF version) and then dives into specific basics of using Mockito. This section covers downloading Mockito and configuring it as a dependency in Eclipse, Maven, and Gradle. The subsection on "Stubbing method calls" provides an example of an application for testing that consists of a jQuery client that communicates with a back-end that appears to be based on Spring Web MVC. The example then demonstrates using Mockito to mock and stub classes used by the back-end class to be tested. Code demonstrates using Mockito.mock(Class) or using static imports so that it can be simply called as mock(Class). This section also introduces use of the @Mock annotation.

Chapter 2 introduces Mockito's "trigger" method when(T) along with the associated "trigger action" methods thenReturn(-), thenThrow(-), thenAnswer(-), and thenCallRealMethod(-). Chapter 2 provides an example of using a unit test method annotated with JUnit 4's @Test(expected="") along with Mockito's thenThrow method.

Mockito Essentials's second chapter illustrates use of and explains Mockito's argument matchers and references org.mockito.Matchers documentation. It then introduces ArgumentMatcher as a "Hamcrest matcher with the predefined describeTo() method" that "allows us to create our own custom argument matchers." The chapter then describes and illustrates the use of JUnit 4 with some common Hamcrest matchers such as equalTo, is, not, either, both, anyOf, and allOf.

The section in Chapter 2 called "Verifying method calls" discusses use of Mockito's static method verify to "verify the invocation" of a method on a mock object and describes situations where this might be desirable.

Chapter 2's final section ("Understanding the Mockito architecture") may have been the most (pleasantly) surprising one for me. I like the author's use of a sequence diagram to illustrate how Mockito uses CGLib (Byte Code Generation Library) to "[apply] the proxy design pattern to create mock objects." I also like that the author provides explanations and code listings that demonstrate how to "create a custom mocking framework to handle external dependencies" with Java reflection and dynamic proxies. Most readers trying to learn basics of Mockito probably don't require this knowledge, but I think it's helpful to understand the tool at the deeper level that this section provides.

Chapter 3: Accelerating Mockito

The third chapter of Mockito Essentials is intended to cover more advanced Mockito topics and begins by addressing the well-known issue of unit testing void methods (including throwing exceptions from void methods and void method callbacks). This part of the chapter also looks at doNothing(), doReturn(), ArgumentCaptor, and InOrder.

Chapter 3 features a section on "spying objects" that states, "A Mockito spy allows us to use real objects instead of mocks by replacing some of the methods with stubbed ones. This behavior allows us to test the legacy code." Text and code listings demonstrate use of Mockito's spy facility and there is a warning to use doReturn() instead of thenReturn() when working with Mockito Spy.

Chapter 3's section "Exploring Mockito Annotations" looks at three Mockito annotations such (@Captor, @Spy, and @InjectMocks). The section "Changing the default Mockito settings" describes configuration of default values returned by "nonstubbed methods of a mock object" using the five available values of the Answers enum.

Chapter 3 introduces Mockito.reset(T...) and provides a caution regarding its use similar to that in the method's Javadoc documentation. A short section of Chapter 3 covers inline stubbing. Another short section describes use of Mockito.mockingDetails (introduced in Mockito 1.9.5) to determine if an object is a mock or spy.

Chapter 4: Behavior-driven Development with Mockito

The fourth chapter of Mockito Essentials opens with the introductory sentence: "This chapter explores Behavior-driven Development (BDD) and how BDD can help you minimize project failure risks." The chapter describes top-down and bottom-up approaches and problems with each to set the context for BDD. The chapter then introduces behavior-driven development with references to Martin Fowler's TestDrivenDevelopment and domain driven design and to Agile Methods for Software Development. The chapter then references and summarizes Dan North's Introducing BDD.

After summarizing BDD, Chapter 4 moves onto "exercising BDD with Mockito." This section introduces BDDMockito and its static given(T) method. An example of using this class and method are included and the BDD-supporting Mockito syntax is briefly described.

Mockito Essentials's Chapter 4's coverage of Mockito BDD support is a relatively small part of the chapter. For developers entirely new to BDD, the entire chapter is worth reading to get an overview of the problems BDD is designed to address. For those familiar with BDD concepts already who just want to see how Mockito can be used to implement BDD testing, the last 3 pages of the chapter should be sufficient. For developers not interested in BDD, the entire chapter could be skipped.

Chapter 5: Unit Testing the Legacy Code with Mockito

Chapter 5 of Mockito Essentials begins with an introductory description of legacy code, references and quotes from the book Working Effectively with Legacy Code, and describes and why legacy code can be do difficult to work with. The chapter then describes how testing frameworks and the Java language can require developers to change otherwise good designs for testability. Given this challenge, the chapter introduces PowerMock.

Mockito Essentials's fifth chapter states, "Mockito could do the things PowerMock does, but it doesn't because those are test smells and strong indications that you are following a poor design." The author goes onto describe some of the typical ways code can be refactored to be more testable without use of PowerMock. The author then asserts, "PowerMock is a fallback for legacy code that they should aim to stop using with time." With these caveats stated, the chapter does a nice job of concisely describing what PowerMock is and how it is able to provide "its special mocking capabilities."

The fifth chapter provides links for information on PowerMock and for downloading PowerMock and then describes using PowerMockito. The chapter features several sections that describe how to apply "mocking capabilities of PowerMockito for untestable constructs" such as stubbing static methods, suppressing static blocks, suppressing a superclass constructor and class's own constructor, suppressing methods, stubbing private methods and final methods, and mocking final classes.

The section of the fifth chapter on "designing for testability with Mockito" "covers the design for testability, or rather, things to avoid in code." This section is not necessarily specific to Mockito because it covers issues common to most mocking frameworks and unit testability. This discussion is useful in terms of describing code patterns and idioms that are not mockable and presenting one or more alternatives for improving their ability to be mocked. Mockito is mentioned specifically during the discussion, but mostly to remind the reader that the code constructs to be tested need to be refactored for mocking with Mockito to be possible. It is repeatedly emphasized in this section that placing "testing impediments" inside these code constructs that are not mockable prevents them from being unit tested and moving those testing impediments to code that is mockable allows other parts to be unit tested while mocking the testing impediments instead of dealing with them directly.

Chapter 6: Developing SOA with Mockito

The sixth chapter of Mockito Essentials opens by stating that the chapter "explores web services, web service styles—SOAP-based and RESTful, web service components, and building and unit testing SOAP and RESTful web services with Mockito." The chapter begins with a brief summary of Service-Oriented Architecture (SOA) and the advantages and characteristics often associated with SOA. It moves from this brief introduction to SOA to web services with the segue that "SOA can rely on web services for interoperability between heterogeneous applications and technologies."

Chapter 6's introduction to web services presents basic characteristics of web services without distinction between SOAP-based web services and REST-based web services. It then introduces JAX-WS and JAX-RS.

Mockito Essentials's sixth chapter begins its deeper dive into SOAP-based web services by listing and briefly describing characteristics of WSDL and briefly describing the two most common approaches to building SOAP-based web services with JAX-WS (top-down/contract-first and bottom-up/Java-first). The section on JAX-WS development provides thorough coverage with text and screen snapshots how to use Eclipse with Apache Tomcat and Apache Axis to write and deploy a JAX-WS/SOAP-based web service and client. This section also describes and illustrates refactoring the code to make it more testable and then testing it and using Mockito for mocking. I have found that the tools are what making working with JAX-WS bearable, so it's not surprising that this is a tool-heavy section and one of the few sections of Mockito Essentials where Eclipse-specific behavior is significant to the narrative.

Chapter 6 also has an in-depth look at developing and testing a REST-based web service with JAX-RS. This section begins with a high-level overview of REST and major concepts that are fundamental to REST such as HTTP, URIs, HTTP status, HATEOAS, etc. Coverage then moves to "building a RESTful web service with Spring Framework." An early sentence is this section states, "This section describes the Spring MVC architecture and how RESTful web applications can be unit tested using Spring MVC." Like the section on JAX-WS, this section provides a thorough overview of developing and testing a JAX-RS/Spring-based RESTful web service using Mockito to mock certain aspects.

Chapter 7: Unit Testing GWT Code with Mockito

The final chapter of Mockito Essentials "provides an overview of Ajax/GWT, explains the Model View Presenter (MVP) pattern and loose coupling, and provides examples and strategies to mock GWT widgets using Mockito." The chapter begins with an introduction to Ajax and an example of JavaScript code using Ajax (XMLHttpRequest).

Chapter 7 describes how Google Web Toolkit (GWT) can be appealing because it hides some of JavaScript's quirks in terms of development and testing and lists several advantages of GWT. The section "Learning the MVP pattern" describes using GWT to implement an application with a Model-View-Presenter design pattern and provides background explanation regarding MVP.

Chapter 7's section "Developing a GWT application using MVP" demonstrates use of Eclipse to create a web application using Google Web Toolkit, compiling the Java code into JavaScript code, and building the overall application. This is a lengthy and detailed section that could be seen as a tutorial on using GWT. It's a completely different section, "Unit testing the GWT code," that addresses unit testing (and using Mockito) the GWT code. In addition to discussing use of PockerMockito with GWT testing, this section introduces GWTMockUtilities and GWTTestCase. I've had little exposure to Google Web Toolkit and did not realize its significant support for unit testing. I also appreciated this section's reference to HtmlUnit.

The "Summary" section of Chapter 7 is really a book summary more than a chapter summary.

General Observations

  • The code listings in the PDF version of Mockito Essentials that I reviewed are black font on white background with no color syntax and no line numbers. There is bold emphasis in many of the Java listings for Java keywords, class attributes' names, variables' names, and for literal strings.
  • Although Eclipse is the IDE used and referenced by the author, a Java developer should be able to use his or her favorite IDE. Most of the references to Eclipse are easily translated to other modern Java IDEs such as NetBeans and IntelliJ IDEA. The notable exceptions to this are the demonstrations of using Eclipse to generate JAX-WS artifacts and to generate Google Web Toolkit applications.
  • Although most of Mockito Essentials is relatively easy to read (I have included several direct quotes in this review to try to establish the relatively easy-to-understand writing style), there are some typos and significantly awkward sentences that can make a few things a bit more difficult to understand and lead me to believe another edit would have been in order. Here are some examples to provide an idea of the level of the typos and awkward sentences:
    • A method name "FindalMethodDependency" is referenced (extra lowercase "d")
    • "This is the better way is to refactor the source and make more test friendly."
    • "Building an application in an unplanned way suffers many problems, such as adding new features, making a huge effort as the architecture becomes rigid, maintaining the software (activities such as bug fixing) can turn into a nightmare, white box testing or unit testing the code becomes very difficult, and conflict and integration issues when many people work with the same or similar features."
    • "@Test(execpted=)" (a juxtaposition of characters I often type myself and the reason I left the IDE's code completion handle this one)
    • "Sometimes, we cannot unit test our code, as the special Java constructs hide the testing impediments (a LAN connection or database connection in a private method, final method, static method, or initialization block), such as private methods, final methods and classes, static methods and initialization blocks, new operator, and so on." (the constructs in parentheses are the "testing impediments" and the constructs at the end of the sentence are the "special Java constructs")
  • I liked that Mockito Essentials contains links to related tutorials, blog posts, articles, and tools' web sites. This is especially handy in the electronic edition with easy copy-and-paste.
  • Despite its title of Mockito Essentials, this book covers more than Mockito essentials.
    • It provides relatively substantial introductions to SOAP-based and REST-based web services and to developing web applications with Google Web Toolkit and Spring MVC. Although these lengthy introductions ultimately lead to some discussion about unit testing and mocking those types of applications, there is a significant amount of time spent on the development before even getting to the testing. This can be seen as a positive or a negative depending on the reader's perspective. If a potential reader knows very little about one of these, he or she might appreciate the significant background. If a reader already knows these well or doesn't care to learn them, these sections are probably extraneous.
    • For the reader interested in "core Mockito," the most interesting chapters of Mockito Essentials will be Chapter 1, Chapter 2, Chapter 3, and Chapter 5. Chapter 1 is more general than simply Mockito and provides good background for those new to mocking and Mockito and could probably be skipped by someone with basic familiarity with mocking and Mockito.
    • Chapter 4 will be of most interest to those practicing behavior-driven development (BDD) or interested in learning more about it and potentially practicing it. It's a relatively short chapter and provides an interesting BDD discussion and practical examples.
    • Chapter 6 will be of primary interest to those developing and testing web services (SOAP-based or REST-based). My guess is that most developers interested in this chapter will already be familiar with JAX-RS or JAX-WS and won't need the detailed introduction to generation of web services with those APIs, but that introductory information might be useful to the reader with less familiarity who wants a taste of web service development in Java.
    • Chapter 7, like the previous chapter on web services, is going to be of most interest to developers who use Google Web Toolkit. As with the web services chapter, the extensive description of generating a GWT-based application is probably not necessary for most of those folks.
    • I liked some of the broad categories and topics covered in Mockito Essentials, but think it's important to emphasize that the book, at times, is broader than Mockito. Although this is always done with the intent of providing examples of using Mockito to mock portions of the generated examples, there are chapters where the general development discussion is longer than the unit testing discussion.
  • I am comfortable recommending Mockito Essentials for the developer who wishes to learn more about basics and uses of Mockito. The most significant caveat for me in making this recommendation is that Mockito provides outstanding online documentation and many of Mockito's most common use cases are well described on its API page (contains 22 code snippets and descriptions as of this writing).

Conclusion

Mockito Essentials covers the basics of Mockito and presents some realistic examples of how Mockito can be used to mock portions of Java-based applications that would otherwise violate fundamental tenets of unit testing and make unit tests less effective. Mockito Essentials provides detailed examples of applying Mockito with other tools and frameworks such as PowerMock, Google Web ToolKit, JAX-WS, and JAX-RS. Along the way, many of the commonly accepted practices for writing effective tests and for effective mocking are introduced and explained.

No comments: