Trifork Blog

EasyMock2 in a Nutshell

October 5th, 2005 by
|

The essential tool for unit testing, EasyMock, has come to a new level. This blog entry introduces the new EasyMock2 release.
While it is still in pre-release stage, I do recommend using EasyMock2 for all your Java 5 projects.

To quote Tammo Freese (Project Founder) from the EasyMock project:

‘I plan no modifications other than bug fixes from this point.’

What’s new

  1. No more need for MockControl objects
  2. Build in argument matchers for most common argument matching (a lot less nuisance of having to write your own ArgumentMatcher)

Step-by-step example

Let’s look at a step-by-step example of using EasyMock2:

  1. Put the following line in your imports:

    import static org.easymock.EasyMock.*;

    Note the static import, this imports all static members (methods in this case) from the EasyMock class.
    More on static imports here: http://java.sun.com/j2se/1.5.0/docs/guide/language/static-import.html.

  2. Create a mock object using the following line (probably in your setup() method):

    myManager = createMock(MyManager.class);

    Note 1. It is still only possible to mock interfaces and NOT classes. However, using EasyMock Class Extension it is possible to mock classes.
    Note 2. The createMock() method is a static method on the EasyMock class. It is still possible to use the methods createStrictMock() and createNiceMock() to respectively create a mock which also verifies the order in which the methods are called and a mock that allows all method calls and returns appropriate empty values by default.
    Important: do not forget to set the mocked object on the class under testing.

  3. Specify behavior for the mock object. This example assumes we expect the method isDebug() to be called on our manager six times and returning false on each occasion:

    expect(myManager.isDebug()).andReturn(false).times(6);

    Note 1. Apart from andReturn(), you could also use andThrow() to throw an exception. You can also use andStubReturn() and andStubThrow() to specify default behavior.
    Note2. In EasyMock2 it is easy to specify the number of times you expect the method to be called (in the example the times(6) call). Next to the times(int) method, there are a number of other convenience methods:

    times(int count)
    times(int min, int max) – expect between min and max calls
    atLeastOnce() – expect the method to be called at least once
    anyTimes() – expect an unrestricted number of calls

  4. Set the mock in the replay state and verify after testing the class under test, similar to calling replay and verify on the MockControl object in the previous EasyMock version:

    replay(myManager);
    classUnderTest.someMethod();
    verify(myManager);

Best new feature

Ok, so far so good, but I left out the best new feature (in my opinion).

Remember a method being called with unknown or different arguments on each call. You had to write your own argument matcher. No more……
Now, for example you can do the following:

myManager.someMethod(eq(“anArgument”),isA(Method.class),notNull());

Note 1. The first argument is equivalent to just calling:
myManager.someMethod("anArgument"
Note 2. The second argument specifies that it expects an instance of the Method class
Note 3. The last argument is expected to not be null
Note 4. Either all arguments of a call have to be given by specifying argument matchers, or none

The list of build in argument matchers is pretty extensive, but ofcourse it is still possible to write your own ArgumentMatcher
Below is a list of all build in argument matchers (copied from the EasyMock2 documentation).

eq(X value)
Matches if the actual value is equals the expected value. Available for all primitive types and for objects.

anyBoolean(), anyByte(), anyChar(), anyDouble(), anyFloat(), anyInt(), anyLong(), anyObject(), anyShort()
Matches any value. Available for all primitive types and for objects.

eq(X value, X delta)
Matches if the actual value is equal to the given value allowing the given delta. Available for float and
double.

aryEq(X value)
Matches if the actual value is equal to the given value according to Arrays.equals(). Available for primitive and object arrays.

isNull()
Matches if the actual value is null. Available for objects.

notNull()
Matches if the actual value is not null. Available for objects.

same(X value)
Matches if the actual value is the same as the given value. Available for objects.

isA(Class clazz)
Matches if the actual value is an instance of the given class, or if it is in instance of a class that extends or implements the given class. Available for objects.

lt(X value), leq(X value), geq(X value), gt(X value)
Matches if the actual value is less than/less or equal/greater or equal/greater than the given value. Available for all numeric primitive types.

Hope this blog entry will help you improve your unit testing! It has definitely reduced the amount of mock code in the tests that I have refactored to EasyMock2. Hopefully the final version will be released very soon.

Comments are closed.