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).

Advertisements

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.

Mocking tutorial. Part 1: JMock

Today I held a mock dojo (one and a half hour) in order to introduce mocking and JMock to my audience. This post is intended to be the first part, which focuses exclusively on JMock. In the second part (I don’t know when I’ll have the time for that) I will go through the very same exercise but with Mockito.

First of all, what is mocking? Well, in the most cases a class has dependencies. Those dependencies have to be somehow broken, so we can test one and only one class at a time. In order to break the dependencies, we have several possibilities; dummies, fakes, stubs and finally mocks. Mocks are special cases of test doubles, because one has to predefine expectations on them; these expectations form a list of calls expected to be received by the mock object. Trough mocking we can isolate all the dependencies of a class, so it can be tested in isolation, without testing the functionality of the dependent classes (remember these are unit tests). For a more accurate introduction of mock objects (which is outside the scope of this post), please be referred to this article: http://en.wikipedia.org/wiki/Mock_object

In order to exemplify the whole process of mocking, we will use the following code (I know its has its issues, but anyway it’s gonna be useful to guide you through the process of mocking):

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. You just create them with an empty body, and it should be OK.
Now, we are ready to create a test case. JUnit4 should be put onto your build path, and JMock jars too. Your test case may be called DocumentReaderTestJMock.

OK, the first thing when you want to use JMock, is to create a JUnit4Mockery and tell the test runner that you are actually using JMock. I usually call these mockeries either mockery, or context. In order to create such a mockery you may want to have something like this:

@RunWith(JMock.class)
public class DocumentReaderTestJMock {

	JUnit4Mockery context = new JUnit4Mockery();
}

Now we have JMock as testrunner (see the annotation of the class) and we’ve also got a mockery. So, we could just mock any type of class, right? Wrong! JMock has originally been designed to be able to mock interfaces only. Should you try mocking a class right now, you’d get an error message telling you that only interfaces can be mocked. Fortunately, JMock defines an extension so it can mock classes too. The resulting declaration is not a beautiful one, but anyway, let’s just see how it works:

@RunWith(JMock.class)
public class DocumentReaderTestJMock {

	JUnit4Mockery context = new JUnit4Mockery() {
		{
			setImposteriser(ClassImposteriser.INSTANCE);
		}
	};
}

OK, now we are really ready to mock classes. Let’s just try it, and create a test case, which will test the exceptional path. In order to do that, we need to have an exception to be thrown while reading document content. In order to have an extra constraint, let’s suppose that our exception is thrown while reading the second section. So, we end up with something like this:

@RunWith(JMock.class)
public class DocumentReaderTestJMock {

	JUnit4Mockery context = new JUnit4Mockery() {
		{
			setImposteriser(ClassImposteriser.INSTANCE);
		}
	};

	final Document document = context.mock(Document.class);
	final Logger logger = context.mock(Logger.class);

	@Test
	public void shouldThrowExceptionWhileReadingDocument()
			throws DocumentException {
		DocumentReader documentReader = new DocumentReader(logger, document);
		final Section section = new Section();

		context.checking(new Expectations() {

			{
				allowing(logger).log(with(any(Level.class)), with(any(String.class)));
				oneOf(document).openDocument();

				oneOf(document).getDocumentTitle();
				will(returnValue("Title"));

				exactly(2).of(document).documentEndReached();
				will(returnValue(false));

				exactly(2).of(document).getSectionBySectionNumber(with(any(int.class)));
				will(onConsecutiveCalls(returnValue(section),
						        throwException(new DocumentException())));

				oneOf(document).closeDocument();
			}
		});

		documentReader.getWholeDocument();
	}
}

Now let’s go through the test case. As you can see, JMock can mock objects through the already-well-known context object. We have two mock objects, a Logger and a Document. Whenever you have such a mock object in JMock, you have to take care of the invocations on that particular mock. This means that you have to enumerate all the method calls on the mock object, along with their parameters and the number of times the methods are called (if you forget any of them, your test case will fail). This part is represented by the anonymous inner class (context.checking); Those instructions inside it have the following structure:

1.) A cardinality number and a mock object as its parameter: oneOf(mockObject), exactly(2).of(mockObject), allowing(mockObject) : By this you can tell how many times a particular method is called on a particular mock object. oneOf means that the invocation is called once and only once, exactly(2) is straightforward, while allowing() means any number of invocations. Other cardinality numbers and values: atLeast(x).of(mockObject), atMost(x).of(mockObject), never(mockObject), ignoring(mockObject). Take care when using the last one: this will completely ignore your mock object!

2.) The method called on the mock object with its parameters. These parameters can be defined two ways:

  • exact values (But watch out when passing in plain old java objects. Those objects won’t be matched unless you have defined an accurate equals() method).
  • Parameter matchers: with(any(Something.class)), with(equal(“Hello World”)). Take care! You cannot mix exact values and matchers inside an expectation. E.g. oneOf(calculatorMock).add(1, with(any(int.class))) will be invalid. It will throw an exception telling you that not all parameters were supplied in the form of matchers. Either use exact values or matchers only. If you are sure about one (or several) parameters only, you have to use the following construct: oneOf(calculatorMock).add(with(equal(1)), with(any(int.class))).

Note that this expectation:

allowing(logger).log(with(any(Level.class)), with(any(String.class)));

could be turned into a more strict one:

exactly(3).of(logger).log(with(equal(Level.SEVERE)), with(any(String.class)));

or if you don’t care about the logger at all, then you can have :

ignoring(logger);

3.) Return statement. JMock can return default values for method calls, but if you want to customize these returned values, of course yo cant. That’s what will(returnValue(aValue)) is used for. If the value you want the function to return  is not compatible with the return type of the method, you -again- get a runtime exception (It says something like tried to return AAA from a method that can only return BBB). Note that you can make JMock simulate that an exception was thrown, by using the will(throwException(new MyException())).

You can observe a very nice functionality of JMock, by looking at the lines:

exactly(2).of(document).getSectionBySectionNumber(with(any(int.class)));
will(onConsecutiveCalls(returnValue(section), throwException(new DocumentException())));

It says that getSectionBySectionNumber() is called exactly two times. When it is called for the first time a section object will be returned, while for the second time an exception will be thrown. This way you don’t have to duplicate code lines, just customize the desired return statements.

Note that the order in which invocations are arranged inside the expectation block doesn’t matter (there is a way -by using the inSequance construct- through which you can force the test runner care about the order of expectations). However, it is necessary to define the expectations before the method under test is called.

I get it all the time that “it is too tiring to write all those expectations with all the correct parameters and all the correct cardinality “. However, I think, it is actually a very good feature. There are cases when a test case can not test anything else but collaborations and, optionally the order in which methods were called. Besides, it happened several times, that I figured out performance issues thanks to JMock cardinalities. When I had to introduce an expectation like exactly(9).of(mockObject) it made clear that resource handling is somehow not efficient.

The rest of the class can be tested similarly, requiring no additional knowledge than presented above. So, be my guest, try to achieve 100% coverage.

XML operations – a refactoring dojo

The katas we’ve had lately made it clear that our teams need to be introduced to several refactoring concepts. I decided that I would take some not-that-good-of-quality code, and organize a dojo so we can refactor it. It’s not that easy to find bad code on the internet, and it’s not that easy to come up with a badly implemented project either. I wasted some days searching, but then BANG! I came across this site: http://refactormycode.com/refactorings/recent/java. Actually this is a very strange page. People post bad code there, someone comes along, refactors the whole thing, and posts it back. For free! Some people are either really committed to the community or just have a lot of free time. Anyway…

The code I’ve taken from that site (and made it even worse a bit) looks like:

/*
 * Constraint: parses input strings in the form:
 * <xml><SvcRsData>a<![CDATA[<sender>John & Smith</sender>]]></SvcRsData></xml>
 */
public class StringFunctions {

	private static String string = "";

	public StringFunctions(String string) {
		this.string = string;
		doProcess(string);
	}

	public static String doProcess(String string) {
		int index = string.indexOf("<SvcRsData>");
		if (index > 0) {
			int index1 = index + 11;
			int index2 = string.indexOf("</SvcRsData>");
			String s1 = string.substring(0, index1);
			String s2 = string.substring(index2);

			return doIt(new StringBuffer(s1).append(
					escapeCDataCharacters(string.substring(index1, index2)))
					.append(s2).toString(), false);
		}

		return doIt(string, false);
	}

	private static String escapeCDataCharacters(String string) {
		StringBuffer sb = new StringBuffer();
		int index = string.indexOf("<![CDATA[");
		String myString = string;
		while (index > 0) {
			int cIndex1 = index + 9;
			int cIndex2 = myString
					.indexOf("]]>");

			sb.append(
					myString.substring(0,
							index)).append(
					doIt(myString.substring(
							cIndex1, cIndex2), true));

			myString = myString
					.substring(cIndex2 + 3);
			index = myString
					.indexOf("<![CDATA[");
		}
		return sb.append(
				myString).toString();
	}

	private static String doIt(String s, boolean extendedCharacterEscape) {
		StringBuffer retval = new StringBuffer();
		short character;
		for (int i = 0; i < s.length(); i++) {
			character = (short) s.charAt(i);
			if (character > 128 ? true
					: extendedCharacterEscape ? (character == 34
							|| character == 38 || character == 60 || character == 62)
							: false) {
				retval.append("&#");
				retval.append(character);
				retval.append(';');
			} else {
				retval.append((char) character);
			}
		}
		return retval.toString();
	}
}

So basically that’s it. We have a great dojo material here, it seems. There are no tests, the names are not that self-explanatory, methods are doing more things than they should be, and simply it’s messy. Refactoring, here we go. Tehre is a lot of work to do here, so let’s not waste time, start working! Adding test cases that cover the code is at least half an hour, another one, one and a half for refactoring.

I’ve ended up with something like this: https://github.com/tamasgyorfi/Refactoring-Dojo; It might seem to be an overkill having four different classes plus one more for the tests, but anyway, this way I could encourage my audience writing small methods and classes (so they won’t be afraid of decomposing logics to different abstraction levels). Unfortunately, I did not take into account the time needed for adding test cases so we had a dojo of one hour only. Never mind, will finish it in a second part.