Update of /cvsroot/mockobjects/mockobjects-java/src/core/com/mockobjects/dynamic In directory sc8-pr-cvs1:/tmp/cvs-serv21824/src/core/com/mockobjects/dynamic Modified Files: Tag: DynamicMockExperiment Mock.java C.java Added Files: Tag: DynamicMockExperiment CallMocker.java CallSet.java SingleCall.java Removed Files: Tag: DynamicMockExperiment MockCall.java MockThrowCall.java CallCounter.java CallBag.java MockReturnCall.java AbstractMockCall.java CallSequence.java CallCollection.java MethodExpectation.java MethodMap.java MockVoidCall.java Log Message: First stab at dynamic mocks with named calls etc. --- NEW FILE: CallMocker.java --- /* * Created on 04-Apr-2003 */ package com.mockobjects.dynamic; import com.mockobjects.*; public interface CallMocker extends Verifiable { Object call( Mock mock, String methodName, Object[] args ) throws Throwable; boolean matches(String methodName, Object[] args); } --- NEW FILE: CallSet.java --- /* * Created on 04-Apr-2003 */ package com.mockobjects.dynamic; import java.util.*; /** * @author dev */ public class CallSet implements CallMocker { private List expectedCalls = new ArrayList(); public CallSet() { super(); // dodgy Auto-generated constructor stub } public Object call(Mock mock, String methodName, Object[] args) throws Throwable { for (Iterator call = expectedCalls.iterator(); call.hasNext();) { CallMocker element = (CallMocker) call.next(); if(element.matches(methodName, args)) { return element.call(mock, methodName, args); } } return null; } public void verify() { for (Iterator call = expectedCalls.iterator(); call.hasNext();) { CallMocker element = (CallMocker) call.next(); element.verify(); } } public void add(CallMocker call) { expectedCalls.add(call); } public boolean matches(String methodName, Object[] args) { return false; } } --- NEW FILE: SingleCall.java --- /* * Created on 04-Apr-2003 * * To change this generated comment go to * Window>Preferences>Java>Code Generation>Code and Comments */ package com.mockobjects.dynamic; import junit.framework.*; import com.mockobjects.constraint.*; import com.mockobjects.util.*; public class SingleCall extends Assert implements CallMocker { private String methodName; private Constraint[] constraints; private boolean wasCalled = false; public SingleCall( String methodName, Constraint[] constraints ) { this.methodName = methodName; this.constraints = (Constraint[])constraints.clone(); } public Object call( Mock mock, String methodName, Object[] args ) throws Throwable { assertFalse( methodName + " has already been called", wasCalled ); assertEquals( methodName + " received the wrong number of arguments", constraints.length, args.length ); for( int i = 0; i < args.length; i++ ) { if( !constraints[i].eval(args[i]) ) { throw new AssertionFailedError( AssertMo.expectedErrorMessage( methodName + " received incorrect argument " + i, AssertMo.join(constraints), AssertMo.join(args) ) ); } } wasCalled = true; return null; } public void verify() { if( !wasCalled ) { throw new AssertionFailedError( methodName + " was not called" ); } } public boolean matches(String methodName, Object[] args) { if( !this.methodName.equals(methodName) ) return false; if( args.length != constraints.length ) return false; for (int i = 0; i < args.length; i++) { if( !constraints[i].eval(args[i]) ) return false; } return true; } } Index: Mock.java =================================================================== RCS file: /cvsroot/mockobjects/mockobjects-java/src/core/com/mockobjects/dynamic/Mock.java,v retrieving revision 1.16 retrieving revision 1.16.2.1 diff -u -r1.16 -r1.16.2.1 --- Mock.java 24 Nov 2002 11:01:00 -0000 1.16 +++ Mock.java 4 Apr 2003 16:47:34 -0000 1.16.2.1 @@ -1,461 +1,72 @@ -/* Copyright (c) 2002 Nat Pryce. All rights reserved. +/* + * Created on 04-Apr-2003 * - * Created on February 10, 2002, 11:06 PM */ package com.mockobjects.dynamic; -import com.mockobjects.Verifiable; -import com.mockobjects.constraint.*; +import java.lang.reflect.*; -import junit.framework.Assert; +import junit.framework.*; -import java.lang.reflect.InvocationHandler; -import java.lang.reflect.Method; -import java.lang.reflect.Proxy; -import java.util.*; +import com.mockobjects.*; - -/** A convenient class for creating simple - * <a href="http://www.mockobjects.com">mock objects</a>. +/** + * @author dev */ -public class Mock - extends Assert - implements InvocationHandler, Verifiable -{ - public static final Object VOID = new Object(); - - /** A convenient constant for defining expectations for methods that - * have no methods. - */ - public static final Constraint[] NO_ARGS = new Constraint[0]; - - - private Class[] _proxy_classes; - private Object _proxy; - private MethodMap methods = new MethodMap(); - private boolean _strict = false; - - private Map _default_results = new HashMap(); - - - /** Creates a new Mock object that mocks the behaviour of - * a single interface. - */ - public Mock( Class interface_to_mock ) { - this( new Class[]{interface_to_mock} ); - } - - /** Creates a new Mock object that mocks the behaviour of - * two interfaces. - */ - public Mock( Class interface1, Class interface2 ) { - this( new Class[]{ interface1, interface2 } ); - } - - /** Creates a new Mock object that mocks the behaviour of - * three interfaces. - */ - public Mock( Class interface1, Class interface2, Class interface3 ) { - this( new Class[] { interface1, interface2, interface3 } ); - } - - /** Creates a new Mock object that mocks the behaviour of - * four interfaces. - */ - public Mock( Class interface1, Class interface2, - Class interface3, Class interface4 ) - { - this( new Class[] { interface1, interface2, interface3, interface4 } ); - } - - /** Creates a new Mock object that mocks the behaviour of - * any number of interfaces. - */ - public Mock( Class[] interfaces_to_mock ) { - _proxy_classes = (Class[])interfaces_to_mock.clone(); - _proxy = createInterface( interfaces_to_mock ); - - setupDefaultResult( byte.class, new Byte((byte)0) ); - setupDefaultResult( short.class, new Short((short)0) ); - setupDefaultResult( int.class, new Integer(0) ); - setupDefaultResult( long.class, new Long(0L) ); - setupDefaultResult( float.class, new Float(0.0f) ); - setupDefaultResult( double.class, new Double(0.0d) ); - setupDefaultResult( boolean.class, Boolean.FALSE ); - setupDefaultResult( char.class, new Character('\0') ); - setupDefaultResult( String.class, "" ); - } - - /** Returns an object that can be cast to any of the interfaces passed - * to this Mock's constructor. This Mock will mock the behaviour of - * calls to the proxy. - */ - public Object proxy() { - return _proxy; - } - - /** Is the mock in strict mode? In strict mode the mock will throw - * {@link junit.framework.AssertionFailedError} exceptions when - * unexpected method calls are made. Otherwise, the mock ignore - * the call or return default arguments. - */ - public boolean isStrict() { - return _strict; - } - - public void setStrict( boolean strict ) { - _strict = strict; - } - - /** Mock the behaviour of a method without requiring that the method - * actually be called. Note: the ExpectedCall may check the arguments - * of the call but should usually not do so. - * - * @param call - * The call to be mocked. - * @throws junit.framework.AssertionFailedError - * The method name is not the name of a method mocked by this - * Mock object. - */ - public void setup( String method_name, MockCall call ) { - checkMethodName( method_name ); - methods.setupCall( method_name, call ); - } - - /** Set up calls to <var>method</var> to return <var>result</var>, - * but do not define any expectations upon arguments to those calls. - * Arguments of calls to <var>method</var> will be ignored. - * - * @param method_name - * The name of the method that will be called. - * @param result - * The result that will be returned from this call. Primitive types - * must be wrapped in the equivalent Java object, and will be unwrapped - * before being returned to the caller of the method. - * @throws junit.framework.AssertionFailedError - * The method name is not the name of a method mocked by this - * Mock object. - */ - public void setupResult( String method_name, Object result ) { - setup( method_name, new MockReturnCall( result ) ); - } - - /** Set up calls to <var>method</var> to throw <var>exception</var>, - * but do not define any expectations upon arguments to those calls. - * Arguments of calls to <var>method</var> will be ignored. - * - * @param method_name - * The name of the method that will be called. - * @param exception - * The exception or error that will be thrown as a result of this call. - * @throws junit.framework.AssertionFailedError - * The method name is not the name of a method mocked by this - * Mock object. - */ - public void setupThrow( String method_name, Throwable exception ) { - setup( method_name, new MockThrowCall( exception ) ); - } - - /** Set up the value returned by methods that have the given result - * type, if no result or exception has been explicitly defined for - * the called method by {@link #setupResult}, {@link #setupThrow}, - * {@link #expectReturn} or {@link #expectThrow}. - * - * @param result_type - * The result type of methods to be mocked. - * @param result_value - * The default value returned by mocked methods that return values - * of type <var>result_type</var>. - */ - public void setupDefaultResult( Class result_type, Object result_value ) { - _default_results.put( result_type, result_value ); - } - - /** Expect a method call and mock the behaviour of that call. - * - * @param call - * An object describing the expected call and mocking its behaviour. - * @throws junit.framework.AssertionFailedError - * The method name is not the name of a method mocked by this - * Mock object. - */ - public void expect( String method_name, MockCall call ) { - checkMethodName( method_name ); - methods.expectCall( method_name, call ); - } - - /** Expect a method call and return a result when it is called. - * - * @param method - * The name of the method that will be called. - * @param args - * An array of {@link com.mockobjects.dynamic.Constraint}s that specify the - * epxected arguments of the method call. The length of the array defines - * the expected arity of the method call. - * @param result - * The result that will be returned from this call. Primitive types - * must be wrapped in the equivalent Java object, and will be unwrapped - * before being returned to the caller of the method. - * @throws junit.framework.AssertionFailedError - * The method name is not the name of a method mocked by this - * Mock object. - */ - public void expectAndReturn( String method, Constraint[] args, Object result ) { - expect( method, new MockReturnCall( args, result ) ); - } - - /** Expect a method call and return a result when it is called. - * - * @param method - * The name of the method that will be called. - * @param arg - * An single object that will be compared with predicate eq() - * @param result - * The result that will be returned from this call. Primitive types - * must be wrapped in the equivalent Java object, and will be unwrapped - * before being returned to the caller of the method. - * @throws junit.framework.AssertionFailedError - * The method name is not the name of a method mocked by this - * Mock object. - */ - public void expectAndReturn( String method, Object arg, Object result ) { - expectAndReturn( method, C.args(C.eq(arg) ), result); - } - - /** Expect a method call with no parameters and return a result when it is called. - * - * @param method - * The name of the method that will be called. - * @param result - * The result that will be returned from this call. Primitive types - * must be wrapped in the equivalent Java object, and will be unwrapped - * before being returned to the caller of the method. - * @throws junit.framework.AssertionFailedError - * The method name is not the name of a method mocked by this - * Mock object. - */ - public void expectAndReturn( String method, Object result ) { - expectAndReturn( method, NO_ARGS, result ); - } - - /** - * Expect a call to a method with a void return type. - * - * @param method - * The name of the method that will be called. - * @param args - * An array of {@link com.mockobjects.dynamic.Constraint}s that specify the - * epxected arguments of the method call. The length of the array defines - * the expected arity of the method call. - * @throws junit.framework.AssertionFailedError - * The method name is not the name of a method mocked by this - * Mock object. - */ - public void expectVoid( String method, Constraint[] args ) { - expect( method, new MockVoidCall( args ) ); - } - - /** - * Expect a call to a method with a void return type. - * - * @param method - * The name of the method that will be called. - * @param arg - * An single object that will be compared with predicate eq() - * @throws junit.framework.AssertionFailedError - * The method name is not the name of a method mocked by this - * Mock object. - */ - public void expectVoid(String method, Object arg) { - expectVoid( method, C.args(C.eq(arg)) ); - } - - /** - * Expect a call to a method with a void return type and no parameters - * - * @param method - * The name of the method that will be called. - * @throws junit.framework.AssertionFailedError - * The method name is not the name of a method mocked by this - * Mock object. - */ - public void expectVoid(String method) { - expectVoid( method, NO_ARGS ); - } - - /** Expect a method call and throw an exception or error when it is called. - * - * @param method - * The name of the method that will be called. - * @param args - * An array of {@link com.mockobjects.dynamic.Constraint}s that specify the - * epxected arguments of the method call. The length of the array defines - * the expected arity of the method call. - * @param exception - * The exception or error that will be thrown as a result of this call. - * @throws junit.framework.AssertionFailedError - * The method name is not the name of a method mocked by this - * Mock object. - */ - public void expectAndThrow( String method, Constraint[] args, Throwable exception ) { - expect( method, new MockThrowCall( args, exception ) ); - } - - /** Expect a method call and throw an exception or error when it is called. - * - * @param method - * The name of the method that will be called. - * @param arg - * An single object that will be compared with predicate eq() - * @param exception - * The exception or error that will be thrown as a result of this call. - * @throws junit.framework.AssertionFailedError - * The method name is not the name of a method mocked by this - * Mock object. - */ - public void expectAndThrow( String method, Object arg, Throwable exception ) { - expectAndThrow( method, C.args(C.eq(arg)), exception ); - } - - /** Expect a method call with no parameters and throw an exception or error when it is called. - * - * @param method - * The name of the method that will be called. - * @param exception - * The exception or error that will be thrown as a result of this call. - * @throws junit.framework.AssertionFailedError - * The method name is not the name of a method mocked by this - * Mock object. - */ - public void expectAndThrow( String method, Throwable exception ) { - expectAndThrow( method, NO_ARGS, exception ); - } - - /** Expect a method not to be called. - * An {@link junit.framework.AssertionFailedError} will be thrown if - * the method is called. - * - * @param methodName - * The name of the method that will not be called. - * @throws junit.framework.AssertionFailedError - * The method name is not the name of a method mocked by this - * Mock object. - */ - public void expectNotCalled( String method_name ) { - checkMethodName( method_name ); - methods.expectNotCalled(method_name); - } - - /** Define an order between two calls. The method named - * <var>subsequent_method</var> <em>must</em> be called after - * the method namd <var>preceding_method</var>, otherwise an - * {@link junit.framework.AssertionFailedError} will be thrown - * when <var>subsequent_method</var> is called. - * - * @throws junit.framework.AssertionFailedError - * Either method name is not the name of a method mocked by this - * Mock object. - */ - public void order( String preceding_method, String subsequent_method ) { - checkMethodName( preceding_method ); - checkMethodName( subsequent_method ); - methods.order( preceding_method, subsequent_method ); - } - - - /** - * @see java.lang.Object#equals(java.lang.Object) - * This version will unpack the inovaction handler if the - * other object is a proxy. - */ - public boolean equals(Object obj) - { - try { - return equals(Proxy.getInvocationHandler(obj)); - } - catch (IllegalArgumentException notAProxy) { - return super.equals(obj); - } - } - - /** Called by the {@link java.lang.reflect.Proxy} to mock the behaviour of an - * invoked method and check expectations. - */ - public Object invoke( Object obj, Method method, Object[] args ) - throws Throwable - { - MethodExpectation expectation = methods.startCall(method.getName()); - try { - return getMatchingMethod(method).invoke( this, args ); - } - catch( NoSuchMethodException ex ) { - return mockCall( expectation, method, args ); - } - } - - protected Object mockCall( Method method, Object[] args ) - throws Throwable - { - return mockCall(methods.startCall(method.getName()), method, args); - } - - protected Object mockCall( MethodExpectation expectation, - Method method, - Object[] args ) - throws Throwable - { - if( expectation.canBeCalled() ) { - return expectation.callAndCheckResult( method, args ); - } else { - assertTrue( "unexpected call to "+method.getName(), !_strict ); - return defaultResult( method.getReturnType() ); - } - } - - - private Method getMatchingMethod(Method method) - throws NoSuchMethodException - { - return getClass().getMethod( method.getName(), method.getParameterTypes() ); - } - - private Object defaultResult(Class return_type) { - return _default_results.get(return_type); - } - - /** - * Fails if not all the expected calls have been made to this mock object. - * @throws junit.framework.AssertionFailedError - * Not all expected calls were made to this mock object. - */ - public void verify() { - methods.verify(); - } - - private Object createInterface( Class[] interface_classes ) { - return Proxy.newProxyInstance( getClass().getClassLoader(), - interface_classes, - this ); - } - - private void checkMethodName( String method_name ) { - for( int i = 0; i < _proxy_classes.length; i++ ) { - if( hasMethod( _proxy_classes[i], method_name ) ) { - return; - } - } - - fail("method " + method_name + - " is not defined by any of the mocked interfaces" ); - } - - private boolean hasMethod( Class c, String method_name ) { - Method[] methods = c.getMethods(); - for( int i = 0; i < methods.length; i++ ) { - if( methods[i].getName().equals(method_name) ) { - return true; - } - } - return false; - } +public class Mock implements Verifiable, InvocationHandler { + private String name; + private Object proxy; + private CallMocker call; + + + public Mock( Class mockedClass, String name) { + this.name = name; + this.proxy = Proxy.newProxyInstance( getClass().getClassLoader(), + new Class[] { mockedClass }, + this ); + } + + public Mock( Class mockedClass ) { + this( mockedClass, mockNameFromClass(mockedClass) ); + } + + public static String mockNameFromClass( Class c ) { + String name = c.getName(); + int dotIndex = name.lastIndexOf('.'); + if( dotIndex >= 0 ) { + return "mock-" + name.substring(dotIndex + 1 ); + } else { + return "mock-" + name; + } + } + + public Object proxy() { + return proxy; + } + + public Object invoke( Object proxy, Method method, Object[] args ) + throws Throwable + { + try { + return call.call( this, method.getName(), (args == null ? new Object[0] : args) ); + } + catch( AssertionFailedError ex ) { + throw new AssertionFailedError( name + ": " + ex.getMessage() ); + } + } + + public void expect(CallMocker mocker) { + call = mocker; + } + + public void verify() { + if( call != null ) { + try { + call.verify(); + } + catch( AssertionFailedError ex ) { + throw new AssertionFailedError( name + ": " + ex.getMessage() ); + } + } + } } Index: C.java =================================================================== RCS file: /cvsroot/mockobjects/mockobjects-java/src/core/com/mockobjects/dynamic/C.java,v retrieving revision 1.1 retrieving revision 1.1.2.1 diff -u -r1.1 -r1.1.2.1 --- C.java 24 Nov 2002 10:59:29 -0000 1.1 +++ C.java 4 Apr 2003 16:47:38 -0000 1.1.2.1 @@ -19,7 +19,7 @@ public static final Constraint IS_ZERO = eq(new Integer(0)); public static final Constraint IS_NOT_ZERO = not(IS_ZERO); - public static final Constraint[] ANY_ARGS = MockVoidCall.ANY_ARGS; + public static final Constraint[] ANY_ARGS = null; public static Constraint same( Object o ) { @@ -94,7 +94,7 @@ */ public static Constraint[] args() { - return Mock.NO_ARGS; + return new Constraint[0]; } public static Constraint[] args(Constraint p) { --- MockCall.java DELETED --- --- MockThrowCall.java DELETED --- --- CallCounter.java DELETED --- --- CallBag.java DELETED --- --- MockReturnCall.java DELETED --- --- AbstractMockCall.java DELETED --- --- CallSequence.java DELETED --- --- CallCollection.java DELETED --- --- MethodExpectation.java DELETED --- --- MethodMap.java DELETED --- --- MockVoidCall.java DELETED --- |