The road so far….

July 10, 2010

Easymock, Assert arguments of method call

Filed under: java — Tags: — Rahul Sharma @ 8:41 pm

EasyMock is used for mocking classes, interfaces and corresponding method calls. When you mock a method call you would like to assert the arguments of the call. Asserting an argument can be in terms of identical arguments – as provided during mock, similar arguments – similarity in terms of class/fields/order etc, or any other kind of assertion possible. The package provides whole bunch of options to assert the same. Here I have listed down a couple of them that can be used under varied situations.

I have created a simple interface whose methods will be mocked by using different options in EasyMock package.

public interface MethodCall {
 void callOne(String string);
 void callOne(Args argOne);
 void callOne(ComparableArgs argOne);
}

class Args {
 String value;
}

class ComparableArgs implements Comparable {
 String value;
 public int compareTo(ComparableArgs o) {
 return value.compareTo(o.value);
 }
}

There are three  methods with different arguments, having different characteristics. One is simple String, other is a custom object and the third imposes some ordering using Comparable.

Now let us  start testing this interface methods

The Simplest Thing

The simplest thing possible is to mock the method call using some arguments. EasyMock uses equals to test arguments equality. If the arguments match equally the test will pass else it will fail.

@Test
public void testOne() {
 MethodCall methodCall = EasyMock.createMock(MethodCall.class);
 methodCall.callOne("one"); // this will use equals
 EasyMock.replay(methodCall);
 methodCall.callOne("one");
 // methodCall.callOne("two"); // equals would fail
 // methodCall.callOne(null);
 EasyMock.verify(methodCall);
}

The call has been mocked by methodCall.callOne(“one”). Now we must call the method using the same argument else the equality test would fail. The String class has an implementation for the equals method and this would work fine. Consequently calls such as  methodCall.callOne(“two”) or methodCall.callOne(null) would fail.

What if there class does not have correct “equals” method ?

There are a couple of options, two of them just assert the class of the object. Both of them have different mechanisms of asserting and thus behave differently from one another.

EasyMock also provides other means by which we can get the required argument and then assert its values/ fields.

Assert argument type by Casting

The simplest way to know if the argument belongs to the required type is to cast it into the required type, if it works its is good else it will fail. We can cast the argument to the required type using EasyMock.anyObject(String.class). This would just cast the argument to the required type. Null can be casted to any type and consequently null can be asserted using this call.

@Test
public void testTwo() {
 MethodCall methodCall = EasyMock.createMock(MethodCall.class);
 methodCall.callOne(EasyMock.anyObject(String.class));
 EasyMock.expectLastCall().anyTimes();
 EasyMock.replay(methodCall);
 methodCall.callOne("One");
 methodCall.callOne("Two");
 methodCall.callOne((String) null);
 EasyMock.verify(methodCall);
}

Assert argument type using InstanceOf

We can assert the class type of the arguments using the EasyMock.isA() method. This would just the assert the type of class using the instanceOf operator,  if we try to test it against null it would fail.

@Test
public void testThree() {
 MethodCall methodCall = EasyMock.createMock(MethodCall.class);
 methodCall.callOne(EasyMock.isA(String.class));
 EasyMock.expectLastCall().anyTimes();
 EasyMock.replay(methodCall);
 methodCall.callOne("One");
 methodCall.callOne("Two");
 // methodCall.callOne(null);// this would fail
 EasyMock.verify(methodCall);
 }

Using Capture API to get the required argument

The package provides the Capture API, using which we can get the argument with which the method has been called. Then we can assert the call first, and if that has happened we can assert the values of the argument. The Capture API is pretty much complete i.e. besides capturing the arguments of single call  you can capture arguments for multiple calls. Using the CaptureType Enum you can get the arguments of First/Last or multiple calls.

@Test
public void testFour() {
 MethodCall methodCall = EasyMock.createMock(MethodCall.class);
 Capture<Args> capturedArgs = new Capture();
 // This would capture the last call alter the data captured with
 // CaptureType
 methodCall.callOne(EasyMock.<Args> capture(capturedArgs));
 EasyMock.expectLastCall().anyTimes();
 EasyMock.replay(methodCall);
 methodCall.callOne((Args) null);
 Args argOne = new Args();
 argOne.value = "One";
 methodCall.callOne(argOne);
 EasyMock.verify(methodCall);
 Args value = capturedArgs.getValue();
 assertNotNull(value);
 assertNotNull(value.value);
}

Check  Arguments during the call using a Delegate

We can also check the arguments during the call using the Expect().andDelegateTo() API. Basically we can create a delegate and when the call happens it will be forwarded to the delegate where all the arguments can be asserted, as required.

@Test
public void testSix() {
 MethodCall methodCall = EasyMock.createMock(MethodCall.class);
 methodCall.callOne(EasyMock.<Args> isA(Args.class));
 MethodCall delegateCall = new MethodCall() {
            public void callOne(ComparableArgs argOne) {}
            public void callOne(Args argOne) {
                assertEquals("one", argOne.value);
            }
            public void callOne(String string) {}
           };
 EasyMock.expectLastCall().andDelegateTo(delegateCall)
    .anyTimes();
 EasyMock.replay(methodCall);
 Args argOne = new Args();
 argOne.value = "one";
 methodCall.callOne(argOne);
 argOne.value = "Two";
 methodCall.callOne(argOne);
 EasyMock.verify(methodCall);
}

Using the Comparable interface

If the argument type implements the Comparable interface or there is a Comparator for the same, then we can use the same to assert the equality or any other logical operation on  the arguments. EasyMock  provides the  EasyMock. cmpEq(), EasyMock. cmp() and other variants like EasyMock. geq(), EasyMock. lt() etc using the Comparable and Comparator.

@Test
public void testFive() {
 MethodCall methodCall = EasyMock.createMock(MethodCall.class);
 ComparableArgs value = new ComparableArgs();
 value.value = "Two";
 methodCall.callOne(EasyMock.<ComparableArgs> cmpEq(value));
 EasyMock.expectLastCall().anyTimes();
 EasyMock.replay(methodCall);
 ComparableArgs argOne = new ComparableArgs();
 argOne.value = "one";
 methodCall.callOne(argOne);
 EasyMock.verify(methodCall);
}

These assert mechanisms are just a snapshot of what is available in EasyMock package.

Besides these there are other ways to assert calls using EayMock.eq(), EasyMock.or(), EasyMock.and(), EasyMock.not() etc, for all kinds of purposes. For arrays there is separate api EasyMock.arrEq(), and its variants,  that can take an array and then assert its length, values etc. You can couple a few of these apis and then assert arguments as per you requirements.

Advertisements

2 Comments »

  1. Thanks for your post,it’s very useful for me!

    Comment by log4j — August 2, 2012 @ 10:44 am

  2. Thanks

    Comment by Amit Ahirrao — July 3, 2013 @ 1:50 am


RSS feed for comments on this post. TrackBack URI

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: