I have been long time wondering if it is possible to improve API of EasyMock Java 1.3 version so that you get rid of MockControls in your test code. So as an experiment I wrote following classes to check how much work does this require. I wanted to achieve same simple API as in EasyMock 2.x but still be Java 1.4 compatible. Also I didn't want to rewrite EasyMock or extend it in any fragile way.
Here are the resulting classes that currently support only returning booleans but with some simple coding it should be possible to make it support whole API of EasyMock:
public class EasyMockHelper { private static MockControl lastInvokedControl; public static ReturnValueSetter expect(boolean b) { return new ReturnValueSetter(lastInvokedControl); } public static Object getMock(Class cl) { Object proxy = Proxy.newProxyInstance(cl.getClassLoader(), new Class[]{cl}, new MockInvocationHandler(MockControl.createControl(cl))); return proxy; } private static class MockInvocationHandler implements InvocationHandler { private final MockControl control; public MockInvocationHandler(MockControl control) { this.control = control; } public MockControl getControl() { return control; } public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { Object retValue; try { retValue = method.invoke(control.getMock(), args); } finally { lastInvokedControl = control; } return retValue; } } public static void replay(Object mock) { getControl(mock).replay(); } private static MockControl getControl(Object mock) { MockInvocationHandler invocationHandler = (MockInvocationHandler) Proxy .getInvocationHandler(mock); return invocationHandler.getControl(); } public static void verify(Object mock) { getControl(mock).verify(); } }
public class ReturnValueSetter { private final MockControl lastInvokedControl; public ReturnValueSetter(MockControl lastInvokedControl) { this.lastInvokedControl = lastInvokedControl; } public void andReturn(boolean b) { lastInvokedControl.setReturnValue(b); } }
And here is basic test:
public class EasyMockHelperTest extends TestCase { private interface Sample { boolean getBoolean(); } public void testExpectReturnTrue() throws Exception { Sample mock = (Sample) EasyMockHelper.getMock(Sample.class); EasyMockHelper.expect(mock.getBoolean()).andReturn(true); EasyMockHelper.replay(mock); assertTrue(mock.getBoolean()); } public void testExpectReturnFalse() throws Exception { Sample mock = (Sample) EasyMockHelper.getMock(Sample.class); EasyMockHelper.expect(mock.getBoolean()).andReturn(false); EasyMockHelper.replay(mock); assertFalse(mock.getBoolean()); } public void testExpectMultipleCalls() throws Exception { Sample mock = (Sample) EasyMockHelper.getMock(Sample.class); EasyMockHelper.expect(mock.getBoolean()).andReturn(false); EasyMockHelper.expect(mock.getBoolean()).andReturn(true); EasyMockHelper.replay(mock); assertFalse(mock.getBoolean()); assertTrue(mock.getBoolean()); } }
Even if above code contains some bugs and does not support all scenarios I think it proves that it should be quite easy to improve EasyMock Java 1.3 version.
Here is the source
Comments (4)
Feb 18, 2008
Risto Alas says:
I like the idea. I don't have time to look into this now but I'll investigate it...I like the idea. I don't have time to look into this now but I'll investigate it later, to see if we can use something like this on our project.
Feb 19, 2008
Ürgo Ringo says:
Aleksei will start implementing this extension. https://intranet.aqris.com/jira/...Aleksei will start implementing this extension. https://intranet.aqris.com/jira/browse/TDO-346
We will keep you updated
Feb 19, 2008
Risto Alas says:
Nice Coould I also request some convenience methods like replayAll()?Nice
Coould I also request some convenience methods like replayAll()?
Feb 19, 2008
Ürgo Ringo says:
Definitely. repleayAll, verifyAll should be availableDefinitely. repleayAll, verifyAll should be available