Update of /cvsroot/mockobjects/mockobjects-java/src/core/com/mockobjects/dynamic In directory usw-pr-cvs1:/tmp/cvs-serv10819/src/core/com/mockobjects/dynamic Added Files: IsGreaterThan.java IsLessThan.java Mock.java ExpectedCall.java IsCloseTo.java P.java Or.java ExpectedReturn.java IsEventFrom.java IsSame.java IsNull.java And.java IsNot.java Predicate.java IsAnything.java ExpectedThrow.java IsEqual.java IsInstanceOf.java Log Message: added dynamic mocks library --- NEW FILE: IsGreaterThan.java --- /* Copyright (c) 2002 Nat Pryce. All rights reserved. * * Created on February 10, 2002, 11:35 PM */ package com.mockobjects.dynamic; /** Is the argument greater than another {@link java.lang.Comparable} value? */ public class IsGreaterThan implements Predicate { private Comparable _object; /** Creates a new instance of IsGreaterThan */ public IsGreaterThan( Comparable o ) { _object = o; } public boolean eval( Object arg ) { return _object.compareTo(arg) < 0; } public String toString() { return "a value greater than <" + _object.toString() + ">"; } } --- NEW FILE: IsLessThan.java --- /* Copyright (c) 2002 Nat Pryce. All rights reserved. * * Created on February 10, 2002, 11:35 PM */ package com.mockobjects.dynamic; /** Is the argument less than another {@link java.lang.Comparable} value? */ public class IsLessThan implements Predicate { private Comparable _object; /** Creates a new instance of IsLessThan */ public IsLessThan(Comparable o) { _object = o; } public boolean eval( Object arg ) { return _object.compareTo(arg) > 0; } public String toString() { return "a value less than <" + _object.toString() + ">"; } } --- NEW FILE: Mock.java --- /* Copyright (c) 2002 Nat Pryce. All rights reserved. * * Created on February 10, 2002, 11:06 PM */ package com.mockobjects.dynamic; import junit.framework.AssertionFailedError; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.util.ArrayList; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.HashMap; import java.util.Set; import com.mockobjects.dynamic.ExpectedCall; import com.mockobjects.dynamic.ExpectedReturn; import com.mockobjects.dynamic.ExpectedThrow; import com.mockobjects.Verifiable; /** A convenient class for creating simple * <a href="http://www.mockobjects.com">mock objects</a>. */ public class Mock extends junit.framework.Assert implements InvocationHandler, Verifiable { /** A convenient constant for defining expectations for methods that * have no methods. */ public static final Predicate[] NO_ARGS = new Predicate[0]; private String _name; private Map _expectations = new HashMap(); private Set _not_called_expectations = new HashSet(); private Map _order_constraints = new HashMap(); private Set _called_methods = new HashSet(); private boolean _strict = false; private Map _default_results = new HashMap(); /** Creates a named Mock object, The name will be included in the messages * of exceptions thrown to indicate violated expectations. */ public Mock( String name ) { _name = name; 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, "" ); } /** Creates a Mock object and automatically assigns a name to it. The assigned * name will include the name of the concrete class and a unique identifier of * this instance, but will not be particularly user friendly when included in * error messages. Therefore, it is recommended that you explictly name mock * objects if you use more than one in the same test case. */ public Mock() { this(null); _name = super.toString(); } /** Returns the Mock's name. */ public String toString() { return _name; } /** 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. */ public void setup( ExpectedCall call ) { _expectations.put( call.getMethodName(), call ); _not_called_expectations.remove( call.getMethodName() ); _called_methods.add( call.getMethodName() ); } /** 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. */ public void setupResult( String method_name, Object result ) { setup( new ExpectedReturn( method_name, null, 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. */ public void setupThrow( String method_name, Throwable exception ) { setup( new ExpectedThrow( method_name, null, 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. */ public void expect( ExpectedCall call ) { _expectations.put( call.getMethodName(), call ); _not_called_expectations.remove( call.getMethodName() ); _called_methods.remove( call.getMethodName() ); } /** 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.Predicate}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. */ public void expectReturn( String method, Predicate[] args, Object result ) { expect( new ExpectedReturn( method, 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 same() * @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. */ public void expectReturn( String method, Object arg, Object result ) { expect( new ExpectedReturn( method, P.arg(P.same(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. */ public void expectReturn( String method, Object result ) { expect( new ExpectedReturn( method, null, 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.Predicate}s that specify the * epxected arguments of the method call. The length of the array defines * the expected arity of the method call. */ public void expectVoid( String method, Predicate[] args ) { expect( new ExpectedReturn( method, args, null ) ); } /** 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 same() */ public void expectVoid(String method, Object arg) { expect(new ExpectedReturn(method, P.arg(P.same(arg)), null)); } /** 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. */ public void expectVoid(String method) { expect(new ExpectedReturn(method, null, null)); } /** 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.Predicate}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. */ public void expectThrow( String method, Predicate[] args, Throwable exception ) { expect( new ExpectedThrow( method, 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 same() * @param exception * The exception or error that will be thrown as a result of this call. */ public void expectThrow( String method, Object arg, Throwable exception ) { expect( new ExpectedThrow( method, P.arg(P.same(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. */ public void expectThrow( String method, Throwable exception ) { expect( new ExpectedThrow( method, null, exception ) ); } /** Expect a method not to be called. * An {@link junit.framework.AssertionFailedError} will be thrown if * the method is called. * * @param method * The name of the method that will not be called. */ public void expectNotCalled( String method ) { _not_called_expectations.add(method); } /** 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. */ public void order( String preceding_method, String subsequent_method ) { Set preceding_calls; if( _order_constraints.containsKey(subsequent_method) ) { preceding_calls = (Set)_order_constraints.get(subsequent_method); } else { preceding_calls = new HashSet(); _order_constraints.put( subsequent_method, preceding_calls ); } preceding_calls.add( preceding_method ); } /** 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 { _called_methods.add( method.getName() ); try { return getClass().getMethod( method.getName(), method.getParameterTypes() ).invoke( this, args ); } catch( NoSuchMethodException ex ) { return mockCall( method, args ); } } protected Object mockCall( Method method, Object[] args ) throws Throwable { String method_name = method.getName(); assertCanBeCalled( method_name ); if( _expectations.containsKey( method_name ) ) { ExpectedCall expected = (ExpectedCall)_expectations.get(method_name); checkCallOrder( method_name ); if( expected.isTestingArguments() ) { checkArguments( expected, args ); } return expected.eval( args ); } else if( _strict ) { throw new AssertionFailedError( _name + ": unexpected call to " + method_name ); } else { return defaultResult( method.getReturnType() ); } } private void checkCallOrder( String method_name ) { if( _order_constraints.containsKey(method_name) ) { assertMethodsHaveBeenCalled( (Set)_order_constraints.get(method_name) ); } } private void checkArguments( ExpectedCall expected, Object[] args ) { int arg_count = (args == null) ? 0 : args.length; assertEquals( _name + ": wrong number of arguments to " + expected.getMethodName() + " method", expected.getArgumentCount(), arg_count ); for( int i = 0; i < arg_count; i++ ) { Object arg = args[i]; if( !expected.testArgument( i, arg ) ) { fail( _name + ": unexpected argument " + (i+1) + " to " + expected.getMethodName() + " method" + ", expected " + expected.describeArgument(i) + ", was " + arg ); } } } private Object defaultResult( Class return_type ) { if( _default_results.containsKey(return_type) ) { return _default_results.get(return_type); } else { return null; } } /** 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() { assertAllExpectedMethodsCalled(); } private void assertAllExpectedMethodsCalled() { assertMethodsHaveBeenCalled( _expectations.keySet() ); } private void assertMethodsHaveBeenCalled( Set method_names ) { Iterator i = method_names.iterator(); while( i.hasNext() ) { assertHasBeenCalled( (String)i.next() ); } } private void assertCanBeCalled( String method_name ) { if( _not_called_expectations.contains(method_name) ) { fail(_name + ": unexpected call to method " + method_name ); } } private void assertHasBeenCalled( String method_name ) { if( !_called_methods.contains(method_name) ) { fail( _name + ": method " + method_name + " was not called" ); } } public Object createInterface( Class interface_class ) { return createInterface( interface_class.getClassLoader(), new Class[]{ interface_class } ); } public Object createInterface( ClassLoader loader, Class interface_class ) { return createInterface( loader, new Class[]{ interface_class } ); } public Object createInterface( ClassLoader loader, Class[] interface_classes ) { return Proxy.newProxyInstance( loader, interface_classes, this ); } } --- NEW FILE: ExpectedCall.java --- /* Copyright (c) 2002 Nat Pryce. All rights reserved. * * Created on February 10, 2002, 11:09 PM */ package com.mockobjects.dynamic; /** An expected call to a method of a mock object */ public abstract class ExpectedCall extends junit.framework.Assert { /** A constant that indicates that an <code>ExpectedCall</code> accepts * any arguments, that is, that the call does not check the arguments * passed to it. */ public static final Predicate[] ANY_ARGS = null; private String _name; private Predicate[] _expected_args; /** Constructs an <code>ExpectedCall</code> that accepts any arguments. * * @param name * The name of the expected method. */ public ExpectedCall( String name ) { this( name, ANY_ARGS ); } /** Constructs an <code>ExpectedCall</code> that checks its arguments. * * @param name * The name of the expected method. * @param expected_args * Predicates that define the valid arguments of the method. */ public ExpectedCall( String name, Predicate[] expected_args ) { _name = name; _expected_args = expected_args; } public String getMethodName() { return _name; } public boolean isTestingArguments() { return _expected_args != null; } /* Pre: isTestingArguments() */ public int getArgumentCount() { return _expected_args.length; } /* Pre: isTestingArguments() */ public boolean testArgument( int n, Object arg ) { return _expected_args[n].eval(arg); } public String describeArgument( int n ) { if( _expected_args == null ) { return "anything"; } else { return _expected_args[n].toString(); } } public abstract Object eval( Object[] args ) throws Throwable; } --- NEW FILE: IsCloseTo.java --- /* Copyright (c) 2002 Nat Pryce. All rights reserved. * * Created on February 10, 2002, 11:35 PM */ package com.mockobjects.dynamic; /** Is the argument a number equal to a value within some range of acceptable * error? */ public class IsCloseTo implements Predicate { private double _error; private double _value; public IsCloseTo( double value, double error ) { _error = error; _value = value; } public boolean eval( Object arg ) { double arg_value = ((Number)arg).doubleValue(); return Math.abs( (arg_value - _value) ) <= _error; } public String toString() { return "a numeric value within " + _error + " of " + _value; } } --- NEW FILE: P.java --- /* Copyright (c) 2002 Nat Pryce. All rights reserved. * * Created on February 14, 2002, 4:02 PM */ package com.mockobjects.dynamic; import com.mockobjects.dynamic.*; /** Convenient factory functions and constants for building predicates. */ public abstract class P { public static final IsAnything IS_ANYTHING = new IsAnything(); public static final IsNull IS_NULL = new IsNull(); public static final Predicate IS_TRUE = new IsEqual(new Boolean(true)); public static final Predicate IS_FALSE = eq(new Boolean(false)); public static final Predicate IS_ZERO = eq(new Integer(0)); public static final Predicate IS_NOT_ZERO = not(IS_ZERO); public static Predicate same( Object o ) { return new IsSame(o); } public static Predicate eq( Object o ) { return new IsEqual(o); } public static Predicate eq( int n ) { return new IsEqual( new Integer(n) ); } public static Predicate eq( long l ) { return new IsEqual( new Long(l) ); } public static Predicate eq( double d ) { return new IsEqual( new Double(d) ); } public static Predicate gt( int n ) { return new IsGreaterThan( new Integer(n) ); } public static Predicate gt( long l ) { return new IsGreaterThan( new Long(l) ); } public static Predicate gt( double d ) { return new IsGreaterThan( new Double(d) ); } public static Predicate gt( char c ) { return new IsGreaterThan( new Character(c) ); } public static Predicate lt( int n ) { return new IsLessThan( new Integer(n) ); } public static Predicate lt( long l ) { return new IsLessThan( new Long(l) ); } public static Predicate lt( double d ) { return new IsLessThan( new Double(d) ); } public static Predicate lt( char c ) { return new IsLessThan( new Character(c) ); } public static Predicate not( Predicate p ) { return new IsNot(p); } public static Predicate and( Predicate p1, Predicate p2 ) { return new And(p1,p2); } public static Predicate or( Predicate p1, Predicate p2 ) { return new Or(p1,p2); } public static Predicate isA( Class c ) { return new IsInstanceOf(c); } /* Helper methods for succinctly constructing Predicate arrays */ public static Predicate[] arg(Predicate p) { return new Predicate[] {p}; } public static Predicate[] args(Predicate p1, Predicate p2) { return new Predicate[] {p1, p2}; } public static Predicate[] args(Predicate p1, Predicate p2, Predicate p3) { return new Predicate[] {p1, p2, p3}; } } --- NEW FILE: Or.java --- /* Copyright (c) 2002 B13media Ltd. All rights reserved. * * Created on February 10, 2002, 11:49 PM */ package com.mockobjects.dynamic; /** Calculates the logical disjunction of two predicates. */ public class Or implements Predicate { Predicate _p1, _p2; public Or( Predicate p1, Predicate p2 ) { _p1 = p1; _p2 = p2; } public boolean eval( Object o ) { if( _p1.eval(o) ) { return true; } else { return _p2.eval(o); } } public String toString() { return "(" + _p1.toString() + " or " + _p2.toString() + ")"; } } --- NEW FILE: ExpectedReturn.java --- /* Copyright (c) 2002 Nat Pryce. All rights reserved. * * Created on February 10, 2002, 11:59 PM */ package com.mockobjects.dynamic; import com.mockobjects.dynamic.ExpectedCall; /** An expected method call that returns a result. */ class ExpectedReturn extends ExpectedCall { private Object _result; public ExpectedReturn( String name, Object result ) { this( name, ANY_ARGS, result ); } public ExpectedReturn( String name, Predicate[] expected_args, Object result ) { super( name, expected_args ); _result = result; } public Object eval( Object[] args ) throws Throwable { return _result; } } --- NEW FILE: IsEventFrom.java --- /** Created on Jun 28, 2002 by npryce * Copyright (c) B13media Ltd. */ package com.mockobjects.dynamic; import java.util.EventObject; /** Tests if the argument is an event announced by a specific object. */ public class IsEventFrom implements Predicate { private Class _event_class; private Object _source; /** Constructs an IsEventFrom predicate that returns true for any object * derived from {@link java.util.EventObject} announced by * <var>source</var>. */ public IsEventFrom( Object source ) { this( EventObject.class, source ); } /** Constructs an IsEventFrom predicate that returns true for any object * derived from <var>event_class</var> announced by * <var>source</var>. */ public IsEventFrom( Class event_class, Object source ) { _event_class = event_class; _source = source; } public boolean eval( Object o ) { if( o instanceof EventObject ) { EventObject ev = (EventObject)o; return _event_class.isInstance(o) && ev.getSource() == _source; } else { return false; } } public String toString() { return "an event of type " + _event_class.getName() + " from " + _source.toString(); } } --- NEW FILE: IsSame.java --- /* Copyright (c) 2002 Nat Pryce. All rights reserved. * * Created on February 10, 2002, 11:35 PM */ package com.mockobjects.dynamic; /** Is the argument the same object as another value? */ public class IsSame implements Predicate { private Object _object; /** Creates a new instance of IsSame * * @param o * The predicate evaluates to true only when the argument is * this object. */ public IsSame(Object o) { _object = o; } public boolean eval( Object arg ) { return arg == _object; } public String toString() { return "the same object as <" + _object.toString() + ">"; } } --- NEW FILE: IsNull.java --- /* Copyright (c) 2002 Nat Pryce. All rights reserved. * * Created on February 10, 2002, 11:33 PM */ package com.mockobjects.dynamic; /** Is the argument null? */ public class IsNull implements Predicate { /** Creates a new instance of IsNull */ public IsNull() { } public boolean eval(Object o) { return o == null; } public String toString() { return "null"; } } --- NEW FILE: And.java --- /* Copyright (c) 2002 B13media Ltd. All rights reserved. * * Created on February 10, 2002, 11:49 PM */ package com.mockobjects.dynamic; /** Calculates the logical conjunction of two predicates. */ public class And implements Predicate { Predicate _p1, _p2; public And(Predicate p1, Predicate p2) { _p1 = p1; _p2 = p2; } public boolean eval( Object o ) { if( !_p1.eval(o) ) { return false; } else { return _p2.eval(o); } } public String toString() { return "(" + _p1.toString() + " and " + _p2.toString() + ")"; } } --- NEW FILE: IsNot.java --- /* Copyright (c) 2002 Nat Pryce. All rights reserved. * * Created on February 10, 2002, 11:35 PM */ package com.mockobjects.dynamic; /** Calculates the logical negation of a predicate. */ public class IsNot implements Predicate { private Predicate _predicate; public IsNot( Predicate p ) { _predicate = p; } public boolean eval( Object arg ) { return !_predicate.eval(arg); } public String toString() { return "not " + _predicate.toString(); } } --- NEW FILE: Predicate.java --- /* Copyright (c) 2002 Nat Pryce. All rights reserved. * * Created on February 10, 2002, 11:21 PM */ package com.mockobjects.dynamic; /** A predicate used to define acceptable method arguments. */ public interface Predicate { /** Evaluates the predicate on argument <var>o</var>. */ boolean eval( Object o ); } --- NEW FILE: IsAnything.java --- /* Copyright (c) 2002 Nat Pryce. All rights reserved. * * Created on February 10, 2002, 11:33 PM */ package com.mockobjects.dynamic; /** A predicate that always returns <code>true</code>. */ public class IsAnything implements Predicate { public IsAnything() { } public boolean eval(Object o) { return true; } public String toString() { return "any value"; } } --- NEW FILE: ExpectedThrow.java --- /* Copyright (c) 2002 B13media Ltd. All rights reserved. * * Created on February 10, 2002, 11:59 PM */ package com.mockobjects.dynamic; import com.mockobjects.dynamic.ExpectedCall; /** An expected method call that results in a thrown exception. */ class ExpectedThrow extends ExpectedCall { private Throwable _exception; public ExpectedThrow( String name, Throwable exception ) { this( name, ANY_ARGS, exception ); } public ExpectedThrow( String name, Predicate[] expected_args, Throwable exception ) { super( name, expected_args ); _exception = exception; } public Object eval( Object[] args ) throws Throwable { throw _exception; } } --- NEW FILE: IsEqual.java --- /* Copyright (c) 2002 Nat Pryce. All rights reserved. * * Created on February 10, 2002, 11:35 PM */ package com.mockobjects.dynamic; /** Is the argument equal to another value, as tested by the * {@link java.lang.Object#equals} method? */ public class IsEqual implements Predicate { private Object _object; /** Creates a new instance of IsEqual */ public IsEqual( Object o ) { _object = o; } public boolean eval( Object arg ) { return arg.equals(_object); } public String toString() { return "a value equal to <" + _object.toString() + ">"; } } --- NEW FILE: IsInstanceOf.java --- /* Copyright (c) 2002 Nat Pryce. All rights reserved. * * Created on February 10, 2002, 11:35 PM */ package com.mockobjects.dynamic; /** Tests whether the argument is an instance of a class. */ public class IsInstanceOf implements Predicate { private Class _class; /** Creates a new instance of IsInstanceOf * * @param theclass * The predicate evaluates to true for instances of this class * or one of its subclasses. */ public IsInstanceOf( Class theclass ) { _class = theclass; } public boolean eval( Object arg ) { return _class.isInstance( arg ); } public String toString() { return "an instance of <" + _class.getName() + ">"; } } |