In my three-part EasyMock Fundamentals series, I will take you through the ins and outs of the open source Java library. EasyMock can be used in conjunction with a unit testing framework, such as JUnit or TestNG, to facilitate better unit testing without all the 2nd degree dependency issues. EasyMock provides the means (through the use of mock objects) to specify the response that will be returned when the code being tested makes calls to external methods. This will allow the result of the unit test to be isolated from variables outside of the scope of the unit test code.

An Introduction to EasyMock Fundamentals

Refer to the official EasyMock documentation for more detailed explanation of the tool (latest as of this writing EasyMock3.1 Docs) including download, setup, and a brief usage example.

Please note that, for the sake of simplicity, not all the details of the code examples have been included.

Stubs vs. Mocks

An alternative to using a mock object is to create a stub object; a lightweight implementation of the interface for the external methods, that just return the expected response. These two approaches are best illustrated with an example.

Let us say you want to write a unit test for an object Foo that does something cool, doSomethingCool(), and uses another object, Emailer, to send emails while doing something cool as follows:

package com.partnet.foo;
public class Foo {
  private Emailer emailer;
  public Foo(Emailer emailer) {
    this.emailer = emailer;
  }
  public void doSomethingCool() {
    // something worthy of being unit tested
    emailer.sendEmail(...);
  }
}
package com.partnet.foo;
public interface Emailer {
  boolean sendEmail(...) throw EmailerException;
}

If you’re trying to test the doSomethingCool() method, you don’t want to, shouldn’t have to, and thankfully don’t need to worry about what emailer.sendEmail() does (assuming the implementation of the call has no impact on the code you’re testing of course).

The assumption here is that the real implementation of Emailer, say it’s called FancyEmailerImpl, is a non-simplistic object that may require some configuration or won’t work in a non-real environment. In this case you do not want to have to create a real FancyEmailerImpl and use it in your testing because again, what it does has no bearing on the code you’re actually trying to test.

Stub Objects

Using the stub object approach, you could create a stubbed-out/dummy version of Emailer like the following:

// stub object
package com.partnet.foo;

public StubEmailer
  implements Emailer
{
  public boolean sendEmail(...) throws EmailerException {
    return true;
  }
}

Simple, easy, done… right? Yep, you can now just setup your unit test as follows and test away:

// stub object use
package com.partnet.foo;

public TestFoo {
  @Test
  public void test() {
    Emailer stubEmailer = new StubEmailer();
    Foo myFoo = new Foo(stubEmailer);

    myFoo.doSomethingCool();
  }
}

The downside to this approach is that you end up building and maintaining a bunch of stub code. Additionally, stub code can be difficult to write as you get into stubbing out more complex objects that you want to test around. For example, if the code you’re testing sets an ID on your Emailer and later retrieves it via setId()/getId() methods, this behavior would need to be stubbed out correctly.

Mock Objects

The alternative to writing stubs is writing mocks, or more correctly, using a mock object library to create mock objects for you. EasyMock is such a library. The following demonstrates how to use EasyMock to mock out the Emailer from above.

// mock object example
package com.partnet.foo;

public TestFoo {
  @Test
  public void test() {
    Emailer mockEmailer = EasyMock.createMock(Emailer.class);
    Foo myFoo = new Foo(mockEmailer);

    myFoo.doSomethingCool();
  }
}

Simple, easy, no stub code to maintain. Even cooler is how you solve the problem mentioned above regarding setId()/getId(). This is where the concept of Expectations comes in (in terms of EasyMock, these are called IExpectationSetters). An Expectation is basically you telling a mock object how to behave and what you expect to happen when you run the unit test code: “When this happens, do this”, “When your getId() method is called, return this value”, “I expect that your setId() method will be called”. After your unit test code has run, you can then ask EasyMock to verify that everything you expected to happen actually occurred so that you can be assured your code does what you think it does.

Downloads

The latest EasyMock files can be downloaded from a link on the EasyMock Download page.

Integration

Add these to the classpath:

  • easymock.jar
  • cglib (2.2) – to perform class mocking
  • Objenesis (1.2) – to perform class mocking

Note that EasyMock only works with Java 1.5.0 and above.


This is the first in my three-part EasyMock Fundamentals series. Please leave your questions and comments in the comment section below and look for my next post next week.

Quick Links

EasyMock Fundamentals — Part 2

EasyMock Fundamentals — Part 3