From: erik Date: Wed, 16 Jul 2008 10:13:22 +0000 (+0000) Subject: resettablemock now also works with concrete classes with a default X-Git-Tag: wamblee-utils-0.2@603~66 X-Git-Url: http://wamblee.org/gitweb/?a=commitdiff_plain;h=6087502ede6181aa20b09b19003311156c55d09c;p=utils resettablemock now also works with concrete classes with a default constructor. Non-default constructors cannot be supported since that would require support from mockito as well (spy() functionality). --- diff --git a/trunk/support/general/src/test/java/org/wamblee/test/ResettableMock.java b/trunk/support/general/src/test/java/org/wamblee/test/ResettableMock.java index 47cc6747..4e321566 100644 --- a/trunk/support/general/src/test/java/org/wamblee/test/ResettableMock.java +++ b/trunk/support/general/src/test/java/org/wamblee/test/ResettableMock.java @@ -6,90 +6,107 @@ package org.wamblee.test; import static org.mockito.Mockito.*; import java.lang.reflect.InvocationHandler; +import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Proxy; +import net.sf.cglib.proxy.Enhancer; +import net.sf.cglib.proxy.MethodInterceptor; +import net.sf.cglib.proxy.MethodProxy; + /** - * Resettable mock is a utility to support reset functionality for mockito. + * Resettable mock is a utility to support reset functionality for mockito. + * * @author Erik Brakkee - * + * * @param */ public class ResettableMock { - private static class MockitoInvocationHandler implements - InvocationHandler { - - private Class _class; - private T _mock; - - public MockitoInvocationHandler(Class aClass) { - _class = aClass; - _mock = mock(aClass); - } - - public void reset() { - _mock = mock(_class); - } - - public T getMock() { - return _mock; - } - - @Override - public Object invoke(Object aProxy, Method aMethod, Object[] aArgs) - throws Throwable { - return aMethod.invoke(_mock, aArgs); - } - } - - /** - * Invocation handler that delegates to the current mockito mock and allows - * creation of a new mock. - */ - private ResettableMock.MockitoInvocationHandler _handler; - - /** - * Proxy object to be passed to tested classes. - */ - private T _proxy; - - /** - * Constructs the resettable mock. - * @param aType Type to mock. Must be an interface type. - */ - public ResettableMock(Class aType) { - if ( !aType.isInterface()) { - throw new IllegalArgumentException("Class '" + aType.getName() + "' must be an interface"); - } - _handler = new MockitoInvocationHandler(aType); - _proxy = (T) Proxy.newProxyInstance(aType.getClassLoader(), - new Class[] { aType }, _handler); - } - - /** - * Resets the mock effectively forgetting all previous interactions and verifications. - */ - public void reset() { - _handler.reset(); - } - - /** - * Gets the current mock object to pass to mockito calls. - * - * @return Mock object. - */ - public T getMock() { - return _handler.getMock(); - } - - /** - * Returns the proxy that your tested classes will used. - * - * @return Proxy object. - */ - public T getProxy() { - return _proxy; - } + private static class MockitoInvocationHandler implements + MethodInterceptor { + + private Class _class; + private T _mock; + + public MockitoInvocationHandler(Class aClass) { + _class = aClass; + _mock = mock(aClass); + } + + public void reset() { + _mock = mock(_class); + } + + public T getMock() { + return _mock; + } + + @Override + public Object intercept(Object aProxy, Method aInterceptedMethod, + Object[] aArgs, MethodProxy aMethodProxy) throws Throwable { + try { + return aInterceptedMethod.invoke(_mock, aArgs); + } catch (InvocationTargetException e) { + throw e.getCause(); + } + } + } + + /** + * Invocation handler that delegates to the current mockito mock and allows + * creation of a new mock. + */ + private ResettableMock.MockitoInvocationHandler _handler; + + /** + * Proxy object to be passed to tested classes. + */ + private T _proxy; + + /** + * Constructs the resettable mock. + * + * @param aType + * Type to mock. Must be an interface or a non-final class with a + * default constructor. + */ + public ResettableMock(Class aType) { + if (!aType.isInterface()) { + throw new IllegalArgumentException("Class '" + aType.getName() + + "' must be an interface"); + } + _handler = new MockitoInvocationHandler(aType); + Enhancer enhancer = new Enhancer(); + enhancer.setSuperclass(aType); + enhancer.setCallback(_handler); + _proxy = (T) enhancer.create(); + } + + /** + * Resets the mock effectively forgetting all previous interactions and + * verifications. + */ + public void reset() { + _handler.reset(); + } + + /** + * Gets the current mock object to pass to mockito calls. + * + * @return Mock object. + */ + public T getMock() { + return _handler.getMock(); + } + + /** + * Returns the proxy that your tested classes will used. + * + * @return Proxy object. + */ + public T getProxy() { + return _proxy; + } } \ No newline at end of file