I am Paul Wilson; Mere Complexities Limited, sells my consulting, coaching, and coding services. I am passionate about Agile, particularly Test Driven Development.


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());
        }
    }
}

0 Comments:

Post a Comment

<< Home

subscribe here subscribe

About me

picture

Conference

RailsConf Europe 2008
Scotland on Rails Organiser

Previous blog posts

Blog archive

Other links: