Index: src/main/groovy/mock/interceptor/MockFor.groovy =================================================================== --- src/main/groovy/mock/interceptor/MockFor.groovy (revision 19142) +++ src/main/groovy/mock/interceptor/MockFor.groovy Wed Feb 03 21:07:06 EST 2010 @@ -19,7 +19,7 @@ /** * Facade over the Mocking details. - * A Mock's expectation is always sequence dependent and it's use always ends with a verify(). + * A Mock's expectation is always sequence dependent and it's use automatically ends with a verify(). * * @see StubFor * @author Dierk Koenig @@ -33,9 +33,12 @@ Map instanceExpectations = [:] Class clazz - MockFor(Class clazz) { + MockFor(Class clazz, boolean interceptConstruction=false) { + if (interceptConstruction && !GroovyObject.isAssignableFrom(clazz)) { + throw new IllegalArgumentException("MockFor with constructor interception enabled is only allowed for Groovy objects but found: " + clazz.name) + } this.clazz = clazz - proxy = MockProxyMetaClass.make(clazz) + proxy = MockProxyMetaClass.make(clazz, interceptConstruction) demand = new Demand() expect = new StrictExpectation(demand) proxy.interceptor = new MockInterceptor(expectation: expect) Index: src/main/groovy/mock/interceptor/MockProxyMetaClass.java =================================================================== --- src/main/groovy/mock/interceptor/MockProxyMetaClass.java (revision 19160) +++ src/main/groovy/mock/interceptor/MockProxyMetaClass.java Wed Feb 03 21:08:34 EST 2010 @@ -28,20 +28,37 @@ public class MockProxyMetaClass extends ProxyMetaClass { + public final boolean interceptConstruction; + /** * @param adaptee the MetaClass to decorate with interceptability */ public MockProxyMetaClass(MetaClassRegistry registry, Class theClass, MetaClass adaptee) throws IntrospectionException { + this(registry, theClass, adaptee, false); + } + + /** + * @param adaptee the MetaClass to decorate with interceptability + */ + public MockProxyMetaClass(MetaClassRegistry registry, Class theClass, MetaClass adaptee, boolean interceptConstruction) throws IntrospectionException { super(registry, theClass, adaptee); + this.interceptConstruction = interceptConstruction; } /** * convenience factory method for the most usual case. */ public static MockProxyMetaClass make(Class theClass) throws IntrospectionException { + return make(theClass, false); + } + + /** + * convenience factory method allowing interceptConstruction to be set. + */ + public static MockProxyMetaClass make(Class theClass, boolean interceptConstruction) throws IntrospectionException { MetaClassRegistry metaRegistry = GroovySystem.getMetaClassRegistry(); MetaClass meta = metaRegistry.getMetaClass(theClass); - return new MockProxyMetaClass(metaRegistry, theClass, meta); + return new MockProxyMetaClass(metaRegistry, theClass, meta, interceptConstruction); } public Object invokeMethod(final Object object, final String methodName, final Object[] arguments) { @@ -83,8 +100,18 @@ /** * Unlike general impl in superclass, ctors are not intercepted but relayed + * unless interceptConstruction is set. */ public Object invokeConstructor(final Object[] arguments) { + if (interceptConstruction && null == interceptor) + throw new RuntimeException("cannot invoke constructor without interceptor"); + + if (interceptConstruction) { + GroovyObject newInstance = (GroovyObject) interceptor.beforeInvoke(null, getTheClass().getSimpleName(), arguments); + newInstance.setMetaClass(this); + return newInstance; + } + return adaptee.invokeConstructor(arguments); } Index: src/main/groovy/mock/interceptor/StubFor.groovy =================================================================== --- src/main/groovy/mock/interceptor/StubFor.groovy (revision 19142) +++ src/main/groovy/mock/interceptor/StubFor.groovy Wed Feb 03 21:07:06 EST 2010 @@ -33,9 +33,12 @@ Map instanceExpectations = [:] Class clazz - StubFor(Class clazz) { + StubFor(Class clazz, boolean interceptConstruction=false) { + if (interceptConstruction && !GroovyObject.isAssignableFrom(clazz)) { + throw new IllegalArgumentException("StubFor with constructor interception enabled is only allowed for Groovy objects but found: " + clazz.name) + } this.clazz = clazz - proxy = MockProxyMetaClass.make(clazz) + proxy = MockProxyMetaClass.make(clazz, interceptConstruction) demand = new Demand() expect = new LooseExpectation(demand) proxy.interceptor = new MockInterceptor(expectation: expect)