Book review: Sujoy Acharya – Mockito essentials

A few weeks back I was contacted by Packt Publishing to review a relatively newly published book: Mockito essentials. Without any further talk, let’s see:

I tried to read the book like I had never seen Mockito, or encountered any of the principles of mocking before. Under these conditions some of the chapters were very useful, others less. At many points I had the impression that examples int this book are (maybe) a bit too advanced for beginners, but not so useful for pros. This is mainly because people completely new to mocking/stubbing/faking may get lost in some rather complex pieces of code, while seasoned mockers are reading more advanced books. Continue reading “Book review: Sujoy Acharya – Mockito essentials”

Book review: Sujoy Acharya – Mastering unit testing using Mockito and JUnit

Some weeks ago, I was contacted by Packt Publishing to write a review about the book above. Without any further introduction, let’s just jump in and see the pros and cons of this book.

Mastering unit testing using Mockito and JUnit is a pretty new book, it was published in July 2014.

Right in the first chapter, the author digs deep into the capabilities of JUnit 4. This is a very thorough analysis of the JUnit API, starting from basic things (like how to write a basic test case) and gradually moving towards more and more advanced topics (test categories, expected exceptions). Anything you’re ever going to use from JUnit is described here – and much more. While reading this chapter I had a feeling that if the reader is an expert, chances are high that they’ve already met most of those method calls and annotations; if they’re new to unit testing, then this chapter may be somewhat too fast.
Every single aspect (method, annotation etc.) is backed by some example code, but unfortunately these problems have little to do with real life applications (like assertTrue(true)). Quick note: the book uses the when_something_then_something naming convention for tests. I like this very much, this is my favorite too, as test names become much more readable.

Chapter 2 introduces automated build tools such as maven (ant, gradle) and Jenkins. I think this is a very good idea, as nowadays such tools are compulsory for a software engineer. However, three build tools (maven, ant and gradle) described in detail (I really mean in detail: how to download and configure tehm, how to put together a simple project) is a bit too much. (I think most readers want to be true masters of unit testing, and not of different build tools. To describe the concept along with an example is awesome and would have been more than enough).

Chapter 3 is very short compared to the others. It describes the test doubles – as defined by Gerard Meszaros, which is really a prerequisite to mocking. Many times people fail to see the difference between all the types of test doubles, so this chapter is very welcome.

Chapter 4 is all about mocking with Mockito. It again dives deep into Mockito with all its annotations, API methods and capabilities.  Although similar to Chapter 1, this chapter introduces a more complex example (manipulating stocks), through which it unfolds different aspects of Mockito. There are very nice tips in this chapter, like inline stubbing (saves a lot of code lines) or configuring mock default behaviors for mocks. I’m looking forward to putting in practice some of the ideas described here.

Chapters 5 and 6 will take you to the world of code coverage and code analysis tools. This is again, very cool idea to talk about in conjunction with unit tests. Maybe I would have liked it more right after chapter 2, so Mocito and its usage could have been one after another.

Chapters 7 and 8 are about using Mockito in real life. Chapter 7 is about testing web application, while Chapter 8 talks about testing the data tier. These, indeed are tough things to handle in real projects, so I like it very much that these chapters made it into the book. However, I think there is a slight focus loss here; these two chapters shouldn’t put that much attention on Spring (MVC and JDBC Template), but rather on general, technology independent problems. Sometimes  I felt like I was reading a book on Spring, with some unit testing and not the other way around.

My favorite parts were the last two chapters. Chapter 9 talks about problems that pop up every single day while fighting huge legacy code bases. Those things described there happen exactly as presented – I encountered almost each and every of them when I was a maintenance guy. The book offers practical solutions on how to overcome these obstacles and get legacy code base under test. This chapter is an awesome one, everybody should know and practice those tricks.

Chapter 10 is about best practices when it comes to unit testing. This chapter is really for the inexperienced, who have just  met unit testing but are not familiar with all the good practices about the framework. This chapter should be a very good starting point for junior programmers at the beginning of their career.

Summary.
Mastering unit testing using Mockito and JUnit has got pretty cool tips and tricks, very thorough analysis of the frameworks and practical applications for everybody out there. One thing I particularly liked is that the book offers a very good overview on all the different reasons why a piece of code becomes hard to test. Nevertheless, I can’t really figure out who is this book for. It is too fast paced for absolute beginners, but somewhat too obvious for experienced engineers – in my honest opinion, some parts may miss the targeted audience.

Having said all these, I’m rating this book 3 out of 5.

Composite Design Pattern Kata

Today’s post is nothing elevated, just two examples from which one can understand this powerful design pattern.

First, let’s do a quick recap, how the pattern actually looks like: 

(if you’re new to design patterns, please find a detailed description here)

The exercises are the following (note that the second one usually looks easier, because it’s easier to imagine. However, you are gonna have a harder time if you want to do that properly using TDD. Mocking recursive structures is not the easiest thing to do):

  1. Implement an application that can draw(no, you don’t really have to draw, just implement the data structures) pictures using rectangles and circles. A picture can be made from primitives (rectangles and circles), primitives combined with other pictures (one or more primitives and at least one other picture – which is composed of primitives), and several pictures combined. (Spoiler: circles and rectangles are leaves, pictures are composite objects)
  2. Implement an application that can compute (yes, you really have to compute) the size of a directory. The size of a directory is equal to the sum of all the files it contains plus the size of its subdirectories. (Hint: you might want to wrap java.io.File objects inside your Leaf and Composite classes. Spoiler: in this case plain files are leaves, directories are composites).

You can find a solution to the second problem here (implementation in Java, unit tested with JUnit and Mockito).

Mocking tutorial. Part 2: Mockito

You might remember from the previous post that we are discovering the possibilities of different mocking frameworks. In the first part of this post series, I was presenting several features of JMock. In the second part we are going to see how those features are similar/different in another popular mocking framework, namely Mockito.

The example through which we exemplify the soul Mockito, is the very same we used for JMock. If you -somehow- don’t remember our example code, then you can find it below:

public class DocumentReader {

	private final Logger logger;
	private final Document document;

	public DocumentReader(Logger logger, Document document) {
		this.logger = logger;
		this.document = document;

	}

	public DocumentContent getWholeDocument() {
		DocumentContent documentContent = null;
		logger.log(Level.SEVERE, "getWholeDocument got called");
		document.openDocument();
		try {
			documentContent = readDocumentSections();
		} catch (DocumentException documentException) {
			logger.log(Level.SEVERE, "DocumentException caught in documentReader.getWholeDocument(Document)");
		} finally {
			document.closeDocument();
			logger.log(Level.SEVERE, "getWholeDocument left");
		}
		return documentContent;
	}

	private DocumentContent readDocumentSections() throws DocumentException {
		DocumentContent documentContent  = new DocumentContent(document.getDocumentTitle());
		int sectionCounter = 0;
		while (!document.documentEndReached()) {
			Section currentSection = document.getSectionBySectionNumber(sectionCounter++);
			documentContent.addSection(currentSection);
		}
		return documentContent;
	}

	public String getDocumentTitle() {
		return document.getDocumentTitle();
	}
}

Document is an empty class, it does not do anything, just defines some methods:

package impl;

public class Document {

	private final String path;

	public Document(final String path){
		this.path = path;

	}

	public void openDocument() {
		//...
	}

	public boolean documentExists() {
		//...
		return true;
	}

	public void closeDocument() {
		//...
	}

	public Section getSectionBySectionNumber(final int sectionNumber) throws DocumentException{
		//...
		return new Section();
	}

	public boolean documentEndReached() {
		return false;
	}

	public String getDocumentTitle() {
		return "Title";
	}
}

DocumentContent is just a simple data holder class:

package impl;

import java.util.ArrayList;
import java.util.List;

public class DocumentContent {

	private final String documentTitle;
	private List<Section>sections = new ArrayList<Section>();

 public DocumentContent(String documentTitle) {
 this.documentTitle = documentTitle;
 }

 public void addSection(Section newSection) {
 sections.add(newSection);
 }
}

All the other referenced classes are empty.

Now, as TDD believers, we can create a new JUnit test case. Let’s call it DocumentReaderTestMockito, in order to be consistent with the naming convention used in the previous post. After the creation of the new file, -as a first step- we have to let the test runner know that we are using Mockito. It is quite similar to what we’ve done in the last post; namely annotate the class with the @RunWith(MockitoJUnitRunner.class) annotation. After this step, you can have something like this:

@RunWith(MockitoJUnitRunner.class)
public class DocumentReaderTestMockito {

}

When using Mockito, you don’t need to create a special object, through which you can create mock object. These mocks can simply be injected automatically, using the @Mock annotation. Remember that you have to annotate your test class with the @RunWith annotation, or the automatical mock injection will not be working.
So, in order to create mock objects with Mockito, you simply need to have something like this:

@RunWith(MockitoJUnitRunner.class)
public class DocumentReaderTestMockito {

	@Mock
	Document document;
	@Mock
	Logger logger;
}

If this was a contest of user-friendliness, Mockito would have the lead over JUnit (that’s it; Mockito is simpler from this point of view). Now, we can write a test case, which (like at the last time) throws an exception when the second Section object is being read. In order to do something like that, you might have something like this:

@RunWith(MockitoJUnitRunner.class)
public class DocumentReaderTestMockito {

	@Mock
	Document document;
	@Mock
	Logger logger;

	@Test
	public void shouldThrowExceptionWhileReadingDocument() throws DocumentException {
		DocumentReader documentReader = new DocumentReader(logger, document);
		when(document.getSectionBySectionNumber(2)).thenThrow(new DocumentException());
		documentReader.getWholeDocument();
	}
}

Quite simple, huh? We just create our mock objects using dependency injection, pass them to the class under test’s instance, and tell Mockito when we want the exception to be thrown. If you look at the code, you may spot that the only Mockito-realted line inside the test case is the following: when(document.getSectionBySectionNumber(2)).thenThrow(new DocumentException());. I don’t think this line needs further comments. It is kind of straight forward. One thing to remember -exactly as in the case of JMock – Mockito returns default objects for method calls. This means zeroes, empty collections and nulls – depending on the return type of the method.

As you may have already noticed, Mockito doesn’t require you to take care of all the method calls on your mock objects. You just tell the desired interactions and you are done. Of course, if you want Mockito to return specific values, you can do that. Let’s take an example. The following test case will test the normal execution flow; the document’s end will be reached at the first call to documentEndReached().

	@Test
	public void shouldThrowExceptionWhileReadingDocument()
			throws DocumentException {
		DocumentReader documentReader = new DocumentReader(logger, document);
		when(document.documentEndReached()).thenReturn(true);

		documentReader.getWholeDocument();
	}

Or, if you want to be sure that the code is working correctly (e.g. we only leave the loop when the document’s end is reached), you just replace the “when” above, with something like this:

when(document.documentEndReached()).thenReturn(false, false, true);

Which is: for the first two invocations of documentEndReached(), we return false, while for the third one we return a true (so we leave the loop).

You might remember the concept of cardinality from JMock. There is a way you can make Mockito care about the number of invocations on your mock objects. This is what the method verify() is used for. Let’s take an example:

	@Test
	public void shouldThrowExceptionWhileReadingDocument()
			throws DocumentException {
		DocumentReader documentReader = new DocumentReader(logger, document);
		when(document.documentEndReached()).thenReturn(false, false, true);
		documentReader.getWholeDocument();

		verify(logger).log(Level.SEVERE, "getWholeDocument got called");
		verify(logger).log(Level.SEVERE, "getWholeDocument left");
	}

Now, if any of the invocations are not happening, our test case will fail. Of course, you may compact the two verify statements into one, if you don’t really care about the log messages. Mockito (just like JMock) defines the concept of argument matcher. Let’s just rewrite the test case to something like this:

	BaseMatcher<Level> isLevel = new BaseMatcher<Level>() {
		public boolean matches(Object item) {
			return item instanceof Level;
		}
		
		@Override
		public void describeTo(org.hamcrest.Description description) {
		}
	};

	@Test
	public void shouldThrowExceptionWhileReadingDocument()
			throws DocumentException {
		DocumentReader documentReader = new DocumentReader(logger, document);
		when(document.documentEndReached()).thenReturn(false, false, true);
		documentReader.getWholeDocument();

		verify(logger, times(2)).log(argThat(isLevel), anyString());
	}

When using Mockito, you can match any kind of object through the method argThat(). In order to be able to match a certain type of object (Level, in our case), you have to define your own matcher. You just simply overwrite the matches() method of the BaseMatcher abstract class, and pass the newly created object to argThat() method as a parameter. There are several predefined matchers too, like anyString(), anyInt(), anySet(), and many many others.

As you can see we’ve also passed a second parameter to the verify() method, that will tell Mockito that we want that certain invocation to happen twice. times(1) is the default value, and it can be omitted like we did before.

As a final example, let’s write a test case that will define all the invocations we need (and for that let’s get back to our first example, the one which cares for exception throwing. Such a way we can compare the final solutions implemented with Mockito and JMock):

	BaseMatcher<Level> isLevel = new BaseMatcher<Level>() {
		public boolean matches(Object item) {
			return item instanceof Level;
		}
		
		@Override
		public void describeTo(org.hamcrest.Description description) {
		}
	};

	@Test
	public void shouldThrowExceptionWhileReadingDocument()
			throws DocumentException {
		DocumentReader documentReader = new DocumentReader(logger, document);
		when(document.getSectionBySectionNumber(2)).thenThrow(new DocumentException());
		
		documentReader.getWholeDocument();

		verify(logger, times(3)).log(argThat(isLevel), anyString());
		verify(document).openDocument();
		verify(document).getDocumentTitle();
		verify(document, times(2)).documentEndReached();
		verify(document, times(2)).getSectionBySectionNumber(anyInt());
		verify(document).closeDocument();
	}

Taking into account the matcher we had to write, we end up with nearly the same complexity as in the previous post. However, Mockito would not notify you if you left out any of the interaction (it would, however, fail the test case if you defined the wrong number of invocations).

Now you have an example with both Mockito and JMock, so pick your favorite and have fun.