Home
subscribe

L'etat, c'est moi

Mere Complexities sells the consulting and development services of me, Paul Wilson.

Conferences

Organising Scotland on Rails
Speaker, RailsConf Europe '08

Archive

Easy Peasy Mock

For various reasons, that I may go into later, I gave up Jmock a few months ago. I still find that fake implementations are useful to have in the testing toolbox. Here is a simple way of faking a subset of interface implementations: for example we might just want to fake getParameter from HttpServletRequest using a Self-Shunt.


public class TestSomeWebThing extends TestCase
{
private String _parameterNameUsed;

public void testSomeServlet() throws Exception { HttpServlet testee = new MyServlet(); testee.service((HttpServletRequest) DummyProxy.dummy(HttpServletRequest.class, this), (HttpServletResponse) DummyProxy.dummy(HttpServletResponse.class, this)); assertEquals(“expectedParam”, _parameterNameUsed); checkTheOtherStuffHappened(); } /**
  • Implements method from HttpServletRequet
    */
    public String getParameter(String parameterName)
    {
    _parameterNameUsed = parameterName;
    return “mavis”;
    }
    ……..
    }

Here is an implementation for DummyProxy:

public class DummyProxy
{
public static Object dummy(Class implementMe, Object partial)
{
return Proxy.newProxyInstance(implementMe.getClassLoader(), new Class[]{implementMe}, new Handler(partial));
}

private static class Handler implements InvocationHandler { private Object _partial; public Handler(Object partial) { _partial = partial; } public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { Method equivalent = findEquivalentImplementation(method); if (equivalent == null) { throw new UnsupportedOperationException(method.getName() + “:” + args); } return equivalent.invoke(_partial, args); } private Method findEquivalentImplementation(Method method) { Method[] implementations = _partial.getClass().getMethods(); for (int i = 0; i < implementations.length; i++) { Method implementation = implementations[i]; if (methodNamesMatch(implementation, method) && methodParametersMatch(method, implementation)) { return implementation; } } return null; } private boolean methodParametersMatch(Method method, Method implementation) { return Arrays.equals(method.getParameterTypes(), implementation.getParameterTypes()); } private boolean methodNamesMatch(Method implementation, Method method) { return implementation.getName().equals(method.getName()); } }

}

All