Mar
6

Using EasyMock to Create Stub Objects

There are two competing philosophies with regard to unit testing strategies; state based testing and behavior based testing. In state based testing we configure a starting state, execute a test method, and then examine the resultant state/returned result. In behavior driven testing we ensure that our test object collaborates with its dependencies in an expected way.

When applying a strictly state driven unit test strategy we can experience an explosion in the number of stub objects in our test code. Our System Under Test (SUT) requires dependencies that operate in a predetermined way (so that we can successfully predict the outcome/resultant state). This is more complex to set up, but gives the advantage that we are less fragile in the face of changes to our SUT implementation.

Our behavior driven brethren are laughing fanatically at our test strategy ideology, whilst enjoying the benefits of EasyMock.
Mock objects are different to stub objects in that they record behavior rather than returning canned values. EasyMock is a nice tool that allows us to record operations and expectations on classes, replay those expectations against the actual operations performed and then verify that what really occurred matches that which was expected. Easy mock makes building a test very easy, although if the implementation changes the order in which methods are called, or the parameters used, or indeed which methods are executed at all, our test may break. This can lead to tests which are potentially fragile, and difficult to maintain.

The ideal of testing purely for state rather than behavior is somewhat of a pipe dream however in that we still have to supply stub objects/dependencies so that our SUT can execute. We still need to make some assumptions about our implementation to know that it will fetch data from a particular stub, or that it will use a particular getter. It is more general however and a stub could be made general enough to support multiple test methods or multiple tests. Getting this right is what makes a unit test, a good unit test.

Wouldn’t it be nice if we could use a tool like EasyMock to generate our stubs, rather than program them over and over again, or maintaining a large set of shared stubs? EasyMock is, thankfully, powerful enough to allow us to create stubs.

In the example we will create a stub for the following interface:

public interface IMyService {

    public Integer getData();

    public String convert(Object object);

}

The code that could be added to a unit test class to provide a stub for this interface with canned responses is as follows:

/**
  * Sets up all mock objects.
  */
@Before
protected void prepareStubs() {
    this.myStubObject = EasyMock.createMock(IMyService.class);
    prepareStubResponses();
}

/**
 * Generates the canned responses.
 */
private void prepareStubResponses() {
    EasyMock.expect(this.myStubObject.getData()).andReturn(new Integer(5)).anyTimes();
    EasyMock.expect(this.myStubObject.convert(EasyMock.anyObject())).andReturn("ABC").anyTimes();
    EasyMock.checkOrder(this.myStubObject, false);
    EasyMock.replay(this.myStubObject);
}

First we create the stub object, then we configure an expected call to “getData” and we return the canned response “new Integer(5)”. The important thing that we have done here is to relax the expected number of calls to “.anyTimes()”. This means that we are not interested in the number of executions. We also switch off the expected ordering of calls. Setting “false” in check order means that EasyMock doesn’t care anymore if “getData” is called first, or if “convert” comes first. Finally we replay the stub in order to “start” it.

There is a shorter way to implement this however using “andStubReturn(..)”. The code would then look as follows:

private void prepareStubResponses() {
    EasyMock.expect(this.myStubObject.getData()).andStubReturn(new Integer(5));
    EasyMock.expect(this.myStubObject.convert(EasyMock.anyObject())).andStubReturn("ABC");
    EasyMock.replay(this.myStubObject);
}

Using “andStubReturn(..)” instead of “andReturn(..)” means that the call can be made any number of times. Order is no longer checked, so we can eliminate the “.anyTimes()” suffix and the order disabling command.

To further improve our stub code, we can use “EasyMock.createNiceMock(..)” instead of “EasyMock.createMock(..)”. A “nice” mock always returns a value regardless of whether behavior has been specified or not, rather than causing an error.

We will never verify the stub, so we are not checking that the methods are called, we don’t care about the order or the number of executions. We simply state that if this method is called, this response is to be returned. The stub can still be made general enough to be shared between tests and it carries no more assumptions than creating an explicit stub does, but eliminates the burden of having lots of extra classes.

Tags: , , , ,

2 Responses to “Using EasyMock to Create Stub Objects”

  1. ExxKA says:

    Nice post.

    I was wondering wether easy mock could be used for building stubs, and you explained it in a nice and easy to understand manner. Short and precise. Thank you.

  2. Nick Wiggill says:

    Yes, thank you; at last a clear explanation that gives only the relevant info for someone new to mocking.