More On Test Doubles

May 13th, 2010 by James Carr

For those of you who are attending my TDD class tonight, you’ll realize that I mentioned several times that learning to use test doubles effectively takes time… I’ve been using test doubles in my tests for half a decade and I still learn something new everytime.

I’ve included some links to material to help you learn more but it will take time for it to soak in. :)

Mockito @Spy Annotation

April 22nd, 2010 by James Carr

In my previous post I went over some of the new annotations and annotation features available in Mockito with the 1.8.3 release and promised the following day I would post details on the @Spy annotation. Well, unfortunately practically a month has passed since then! But fear not, here is the overview of the @Spy annotation that I promised. :)

Using It

Using the @Spy annotation is quite easy… just use the MockitoJunit4Runner and annotate a real object instance as follows:

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

import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Spy;
import org.mockito.runners.MockitoJUnitRunner;
import static org.mockito.Mockito.*;
import static org.junit.Assert.assertThat;
import static org.hamcrest.CoreMatchers.*;

@RunWith(MockitoJUnitRunner.class)
public class SpyExample {
	@Spy
	private List<String> list = new ArrayList<String>();

}

This will essentially proxy the real ArrayList implementation with a CGLib proxy. No big deal there. Let’s try stubbing a call so that it returns “hey” if we request index 32:

        @Test
	public void spyExample(){
		when(list.get(32)).thenReturn("hey");

		assertThat(list.get(32), equalTo("hey"));
	}

This blows up in our face with a big hairy IndexOutOfBoundsException while trying to stub the method call out. Duh… it’s calling the real implementation! Therefore we opt to use doReturn(...) instead as it allows us to stub the method we want without calling the real thing.

@RunWith(MockitoJUnitRunner.class)
public class SpyExample {
	@Spy
	private List<String> list = new ArrayList<String>();
	@Test
	public void spyExample(){
		doReturn("hey").when(list).get(32);

		assertThat(list.get(32), equalTo("hey"));
	}
}

If we rerun the example we will now see green bar rather than IndexOutOfBoundsException. We can still call real methods like add, remove, size, etc and they’ll still behave as expected; only when get(32) is called will it stub the call and return the canned value.

For the most part, I’m not a fan of this technique. In the real world I’d either choose between using the real thing (which I would most certainly ALWAYS do if it were a collection or some other base type) or prefer a wholesome complete stub using @Mock (but adhering to the rule that you only mock/stub objects you actually own).

Sadly there are always weird cases where you need to do it to make something easier to test… a good example was some legacy code I was dealing with where the test interacted with a real object to manipulate graphics in the UI. Those interactions needed to remain intact in order for the existing tests to pass, however one method caused a web service call that made the tests brittle and unpredictable. Spying that object and stubbing out the method that made the web service call was the best way to exercise the different scenarios around what that method returned. “Fixing” the collaborator’s API itself or isolating it from the class under test is a whole separate issue. :)

Verifying Messages Between Collaborators

A really useful feature I find in using spies is the ability to verify messages passed to a real collaborator in a big ball of mud type of system. Imagine this scenario: you pick up a story that is to just modify some logic in how messages are passed from one object to another. Sounds simple, until you look at the existing unit test:

public class CustomerHandlerBOTest {
	private ComplexClassThatDoesAlot formulator = DumbStaticFactory.create();
	private CustomerHandlerBO bo = new CustomerHandlerBO(formulator);

	....
}

The class names and that static factory are bad enough, but let’s imagine the code has gotten itself to the situation where simply providing complete test double for ComplexClassThatDoesAlot will force you to introduce test doubles for 20 other objects. Or perhaps the method is large and the default behavior of the collaborator allows you to execute the code that needs to execute to get you to where you want. You can simply write a verification of the argument passed to it and then make the modification you need to.

@RunWith(MockitoJUnitRunner.class)
public class CustomerHandlerBOTest {
	@Spy
	private ComplexClassThatDoesAlot formulator = DumbStaticFactory.create();
	@Captor
	private ArgumentCaptor<Item> arg;
	private CustomerHandlerBO bo = new CustomerHandlerBO(formulator);

	@Test
	public void shouldPassItemRequestWithExpectedCalculation(){
		...
		bo.calculate(BULK_ORDER);
		verify(formulator).audit(arg.capture());

		Item actualItemAudited = arg.getValue();
		assertThat(actualItemAudited.getPrice(), equalTo(EXPECTED_CALCULATED_PRICE));
	}

Of course, once the tests pass I might start applying some obvious refactorings starting as renaming away from those hideous names and either eventually get to the point where a @Spy is no longer needed or at least have that piece under test. The good thing about this is you can verify the interaction between these two objects without having to crack open encapsulation through a backdoor default or protected method (something I’ve been guilty of).

You Can Stub Internal Calls

I’ve seen situations where someone was dealing with legacy code and wanted to do this:

doReturn(1).when(bookingSystem).getActiveReservations();

bookingSystem.processReservations();

Where processReservations() makes a call to getActiveReservations() internally. Although this clearly hints at a hidden collaborator that needs to exist or break free from bookingSystem, Mockito apparently will let you get away with this. I seriously wouldn’t suggest it when test driving fresh code, again but there’s always those situations where you have no options.

Hope that is useful for you… overall I find the @Spy annotation to simply be a useful tool for fighting legacy code but should be used with care when specifying fresh code, if at all.

Fine Grained Stub Behavior With Mockito

October 18th, 2009 by James Carr

Continuing a trend of Mockito related articles, I thought I’d blog about using another feature I recently discovered while trying to figure out how to implement fine grained behavior in mockito.

First, let me set the stage… I had a method call I was writing examples for that was a typical Castor marshal operation, which often looks something like this:

StringWriter w = new StringWriter();
marshaller.setWriter(w);
marshaller.marshal(obj);
channel.send(w.toString());

Yeah I know… it looks like shit. But sometimes APIs force that on you. Anyway, I wanted to write an example illustrating that the channel received a message that was the result of whatever marshaller wrote to the output stream, but this was a little difficult to do (but easy to do with hard coded subclasses and lots and lots of boilerplate code).

The answer comes with, well, the Answer interface. To illustrate this, let me set up an example. Given I have started a unit test that looks like this:

@RunWith(MockitoJUnitRunner.class)
public class MessageServiceTest {
	@Mock private Marshaller marshaller;
	@Mock private Channel channel;
	private MessageServiceImpl messagService;

	@Before
	public void before(){
		messagService = new MessageServiceImpl();
		messagService.setChannel(channel);
		messagService.setMarshaller(marshaller);
	}

	@Test
	public void shouldWriteMarshalledDataOutToChannel(){

	}
}

We want to be able to verify that the channel (which is a simple interface with a send(String arg) method) receives whatever String the marshaller wrote to the provided Writer. Now, because the writer is constructed in the class itself, it’s difficult to stub this out. So in order to make the writer have SOMETHING written to it, we set up an answer to be invoked both when marshaller.setWriter(..) and when the marshaller.marshall(..) method is called:

private class MarshalAnswer{
		private Writer writer;
		public Answer<Writer> respondToSetWriter(){
			return new Answer<Writer>() {
				public Writer answer(InvocationOnMock invocation) throws Throwable {
					Writer w = (Writer) invocation.getArguments()[0];
					writer = w;
					return null;
				}
			};
		}
		public Answer<Object> respondToMarshall(final String writeThis){
			return new Answer<Object>(){
				public Object answer(InvocationOnMock invocation)
						throws Throwable {
					writer.write(writeThis);
					return null;
				}
			};
		}
	}

Bleh… lots and lots of boilerplate code because of the interfaces, but oh well. Here’s the revised test case in action:

@RunWith(MockitoJUnitRunner.class)
public class MessageServiceTest {
	@Mock private Marshaller marshaller;
	@Mock private Channel channel;
	private MessageServiceImpl messageService;
	private Invoice invoice;
	private MarshalAnswer answers;
	@Before
	public void before(){
		messageService = new MessageServiceImpl();
		messageService.setChannel(channel);
		messageService.setMarshaller(marshaller);
		invoice = new Invoice();
		answers = new MarshalAnswer();
	}

	@Test
	public void shouldWriteMarshalledDataOutToChannel() throws Exception{
		doAnswer(answers.respondToSetWriter()).when(marshaller).setWriter(any(Writer.class));
		doAnswer(answers.respondToMarshall("<someresult/>")).when(marshaller).marshal(invoice);

		messageService.send(invoice);

		verify(channel).send("<someresult/>");
	}
...

I could have just created the respondTo methods in the TestCase itself, but I wanted to keep it separated by putting it in a helper class.

So now we run the test and we should see the following:

Fair enough… lets add the following code to the method we’re describing and rerun:

public void send(Invoice invoice) throws Exception{
		StringWriter writer = new StringWriter();
		marshaller.setWriter(writer);
		marshaller.marshal(invoice);
		channel.send(writer.getBuffer().toString());
	}

We rerun and sure enough, green bar! The way it works is pretty simple… whenever setWriter gets invoked, the Answer object gets called and the argument is available within it (in this case the writer) which we can then store to use for the marshal call. When marshal gets called, our Answer we defined gets called and writes whatever we told it to.

While this does provide us with a useful tool when requiring some slightly complex behavior in our collaborator interactions (in this case, we essentially needed to capture what was passed to the writer, which was acting as a hidden output variable) I’d still recommend avoiding them when you can. :)

Mockito: Verifying Details of an Object Passed to a Collaborator

September 28th, 2009 by James Carr

Recently I was BDD’ing a class, and the behavior I needed to describe happened to be an object created internally (a simple value object) populated with a few attributes and passed to a collaborator. The old way I might be tempted to do this is just create a concrete implementation of the collaborator that stores the argument passed to it, then get it back and verify some outcome on it.

But I wondered if there was a way to do it with Mockito without it looking crappy. And apparently there is a way to verify values on an argument to a collaborator using ArgumentCaptor.

Read More »