Mocking classes with Easymock
[ vmassol ] 12:10, Sunday, 9 November 2003

Joel Shellman has coded an extension (easymock-patch-1.0.jar) of EasyMock which allows to mock class (and not only interfaces).

To use it:

  • put the extension jar in front of the easymock jar in your classpath (it works with Easymock 1.0 only, not with the new 1.0.1b which has modifications for extending Easymock). It overrides the MockControl class by a new one accepting a class as parameter as shown below.
  • add cglib to your classpath (I've tried it with version rc2-1.0).
  • add bcel to your classpath (I've tried it with version 5.1).

Here's an example. First let's start by the class we wish to mock:

package test;

public class Calculator
{
     private int amount;
     
     public Calculator(Integer amount)
     {
          this.amount = amount.intValue();
      }
     
     public int compute()
     {
          return this.amount;
      }
}

Here's now the class we wish to test (it uses the Calculator class):

package test;

public class Account
{
     public int computeBalance(Calculator calculator)
     {
          return calculator.compute();
      }
}

Now, here's our test of computeBalance . Notice that we are mocking the Caculator class:

package test;

import org.easymock.MockControl;

import junit.framework.TestCase;

public class AccountTest extends TestCase
{
     public void testComputeBalance()
     {
          Account test = new Account();
          
          MockControl control = MockControl.createControl(Calculator.class,
              new Class[]{Integer.class}, new Object[]{new Integer(5)});
          Calculator mock = (Calculator) control.getMock();
          
          mock.compute();
          control.setDefaultReturnValue(10);
          control.replay();
          
          int result = test.computeBalance(mock);
          assertEquals(10, result);
      }
}

Note: I don't know how to instantiate a constructor taking primitive types. Don't know if it is supported.

That's nice. However, there are a few drawbacks I can see:

  • It doesn't encourage refactoring and creating interfaces (which is the right way to go in most cases). However, it can still be useful in some cases like when mocking third party classes which do not have interfaces (and there are quite a lot of them, especially in the JDK...)
  • It doesn't work with final classes. Thus not possible to mock the JDK's URL class for example. It also won't work with private constructors of course
  • It forces to know the constructor values when creating the mock
  • It still doesn't help in cases where it is no easy to introduce the mock in the class under test. In that regards, it's less powerful than interception (a la AOP).

So it's not a silver bullet but it will certainly help in cases where you have no control over the sources (like when using third-party libraries.


Comments

>>Note: I don't know how to instantiate a
>> constructor taking primitive types. Don't
>> know if it is supported.

Yes it's supported.

if you have this:
public class Xpto
{
public Xpto(int aVvalue() {}
}

use

Constructor c = Xpto.class.getConstructor(new Class[]{Integer.TYPE});

Object o = c.newInstance(new Object[] { new Integer(100)});


Every class representation of a primtitive type has a static field called TYPE which need to be used to specify primitive types (CLASS) as arguments for methods in reflection.

Other way is to use jakarta's BeanUtils package. I think they have some util classes to handle that in a simple way.

have fun.
Jorge Sousa

--Jorge Sousa, March 25, 2004 01:17 PM

I think the easymock-patch-1.0.jar is very good.
I really want to use it.

--Yukitaka Kobayashi, October 15, 2004 07:38 AM

Am not able to download easymock-patch-1.0.jar.. could anyone please tell me where to download it from?
Looks mighty interesting

--ajeesh, February 17, 2006 04:11 AM

ajeesh, what you want to look at is Mocquer. Mocquer is a similar mock tool as EasyMock. With the help of Dunamis Project, it extends the function of EasyMock to support mock object creation for both class and interface.

--Ronny N, August 30, 2006 09:53 AM

easymock does not support for classes.
means do not need to create mock object for classes.
we can use easymock for interface.

--pankaj khare, January 9, 2008 10:24 AM

i am not understanding for this example because
creatControl method does not support these parameters.what is solution?

--pankaj khare, January 25, 2008 07:47 AM
Post a comment









Remember personal info?