Author: mbenson Date: Tue Dec 24 00:08:43 2013 New Revision: 1553232 URL: http://svn.apache.org/r1553232 Log: add support for stubbing array elements of a stub
Modified: commons/proper/proxy/branches/version-2.0-work/core/src/main/java/org/apache/commons/proxy2/stub/BaseTrainer.java commons/proper/proxy/branches/version-2.0-work/core/src/main/java/org/apache/commons/proxy2/stub/TrainingContext.java commons/proper/proxy/branches/version-2.0-work/test/src/test/java/org/apache/commons/proxy2/stub/AbstractStubTestCase.java commons/proper/proxy/branches/version-2.0-work/test/src/test/java/org/apache/commons/proxy2/stub/StubBuilderTest.java commons/proper/proxy/branches/version-2.0-work/test/src/test/java/org/apache/commons/proxy2/stub/StubInterface.java Modified: commons/proper/proxy/branches/version-2.0-work/core/src/main/java/org/apache/commons/proxy2/stub/BaseTrainer.java URL: http://svn.apache.org/viewvc/commons/proper/proxy/branches/version-2.0-work/core/src/main/java/org/apache/commons/proxy2/stub/BaseTrainer.java?rev=1553232&r1=1553231&r2=1553232&view=diff ============================================================================== --- commons/proper/proxy/branches/version-2.0-work/core/src/main/java/org/apache/commons/proxy2/stub/BaseTrainer.java (original) +++ commons/proper/proxy/branches/version-2.0-work/core/src/main/java/org/apache/commons/proxy2/stub/BaseTrainer.java Tue Dec 24 00:08:43 2013 @@ -17,6 +17,10 @@ package org.apache.commons.proxy2.stub; +import java.lang.reflect.Array; +import java.util.ArrayList; +import java.util.List; + import org.apache.commons.lang3.ArrayUtils; import org.apache.commons.lang3.Validate; import org.apache.commons.lang3.reflect.TypeUtils; @@ -28,19 +32,19 @@ import org.apache.commons.proxy2.interce public abstract class BaseTrainer<S extends BaseTrainer<S, T>, T> { -//---------------------------------------------------------------------------------------------------------------------- -// Fields -//---------------------------------------------------------------------------------------------------------------------- + // ---------------------------------------------------------------------------------------------------------------------- + // Fields + // ---------------------------------------------------------------------------------------------------------------------- public final Class<T> traineeType; -//---------------------------------------------------------------------------------------------------------------------- -// Constructors -//---------------------------------------------------------------------------------------------------------------------- + // ---------------------------------------------------------------------------------------------------------------------- + // Constructors + // ---------------------------------------------------------------------------------------------------------------------- /** - * Create a new {@link BaseTrainer} instance. This constructor should only be called - * by classes that explicitly assign the T parameter in the class definition. - * This should include basically any runtime-usable class. + * Create a new {@link BaseTrainer} instance. This constructor should only + * be called by classes that explicitly assign the T parameter in the class + * definition. This should include basically any runtime-usable class. */ protected BaseTrainer() { @@ -56,22 +60,22 @@ public abstract class BaseTrainer<S exte return; } @SuppressWarnings("unchecked") - final Class<T> resolvedVariable = - (Class<T>) TypeUtils.getRawType(BaseTrainer.class.getTypeParameters()[1], getClass()); + final Class<T> resolvedVariable = (Class<T>) TypeUtils.getRawType(BaseTrainer.class.getTypeParameters()[1], + getClass()); Validate.isTrue(resolvedVariable != null, "Trainee type was not specified and could not be calculated for %s", - getClass()); + getClass()); this.traineeType = resolvedVariable; } -//---------------------------------------------------------------------------------------------------------------------- -// Abstract Methods -//---------------------------------------------------------------------------------------------------------------------- + // ---------------------------------------------------------------------------------------------------------------------- + // Abstract Methods + // ---------------------------------------------------------------------------------------------------------------------- protected abstract void train(T trainee); -//---------------------------------------------------------------------------------------------------------------------- -// Other Methods -//---------------------------------------------------------------------------------------------------------------------- + // ---------------------------------------------------------------------------------------------------------------------- + // Other Methods + // ---------------------------------------------------------------------------------------------------------------------- protected <R> R any(Class<R> type) { @@ -156,7 +160,9 @@ public abstract class BaseTrainer<S exte public <R> WhenObjectArray<R> when(R[] expression) { - return new WhenObjectArray<R>(); + @SuppressWarnings("unchecked") + final Class<? extends R> componentType = (Class<? extends R>) expression.getClass().getComponentType(); + return new WhenObjectArray<R>(componentType); } public WhenCharArray when(char[] expression) @@ -170,9 +176,9 @@ public abstract class BaseTrainer<S exte return (S) this; } -//---------------------------------------------------------------------------------------------------------------------- -// Inner Classes -//---------------------------------------------------------------------------------------------------------------------- + // ---------------------------------------------------------------------------------------------------------------------- + // Inner Classes + // ---------------------------------------------------------------------------------------------------------------------- protected abstract class BaseWhen<R> { @@ -188,13 +194,13 @@ public abstract class BaseTrainer<S exte public S thenAnswer(ObjectProvider<? extends R> provider) { - return then(InterceptorUtils.provider(provider)); + return then(InterceptorUtils.provider(provider)); } public S then(Interceptor interceptor) { - trainingContext().then(interceptor); - return self(); + trainingContext().then(interceptor); + return self(); } } @@ -245,7 +251,7 @@ public abstract class BaseTrainer<S exte protected class WhenIntArray extends BaseWhen<int[]> { - public S thenReturn(int... values) + public S thenReturn(int... values) { trainingContext().then(InterceptorUtils.constant(ArrayUtils.clone(values))); return self(); @@ -254,7 +260,7 @@ public abstract class BaseTrainer<S exte protected class WhenLongArray extends BaseWhen<long[]> { - public S thenReturn(long... values) + public S thenReturn(long... values) { trainingContext().then(InterceptorUtils.constant(ArrayUtils.clone(values))); return self(); @@ -263,7 +269,7 @@ public abstract class BaseTrainer<S exte protected class WhenObject<R> extends BaseWhen<R> { - public S thenReturn(R value) + public S thenReturn(R value) { trainingContext().then(InterceptorUtils.constant(value)); return self(); @@ -279,13 +285,13 @@ public abstract class BaseTrainer<S exte } /** - * Intermediate result of a when(Class) call. - * Provided because it is such a common case to have a mismatch between a - * declared Class<?> return type and the bound parameter of a class literal. + * Intermediate result of a when(Class) call. Provided because it is such a + * common case to have a mismatch between a declared Class<?> return type + * and the bound parameter of a class literal. */ protected class WhenClass extends BaseWhen<Class<?>> { - public S thenReturn(Class<?> value) + public S thenReturn(Class<?> value) { trainingContext().then(InterceptorUtils.constant(value)); return self(); @@ -294,16 +300,55 @@ public abstract class BaseTrainer<S exte protected class WhenObjectArray<R> extends BaseWhen<R[]> { - public S thenReturn(R... values) + private final Class<? extends R> componentType; + + private WhenObjectArray(Class<? extends R> componentType) + { + this.componentType = componentType; + } + + public S thenReturn(R... values) { trainingContext().then(InterceptorUtils.constant(ArrayUtils.clone(values))); return self(); } + + public StubArrayBuilder<R> thenBuildArray() + { + return new StubArrayBuilder<R>(componentType); + } + } + + protected class StubArrayBuilder<R> + { + private final Class<? extends R> componentType; + private final List<R> elements = new ArrayList<R>(); + + private StubArrayBuilder(Class<? extends R> componentType) + { + this.componentType = componentType; + } + + public StubArrayBuilder<R> addElement(BaseTrainer<?, R> trainer) + { + final R trainee = trainingContext().push(trainer.traineeType); + trainer.train(trainee); + elements.add(trainingContext().<R> pop()); + return this; + } + + public S build() + { + @SuppressWarnings("unchecked") + final R[] array = elements.toArray((R[]) Array.newInstance(componentType, elements.size())); + trainingContext().then(InterceptorUtils.constant(array)); + return self(); + } } protected class WhenShortArray extends BaseWhen<short[]> { - public S thenReturn(short... values) + public S thenReturn(short... values) { trainingContext().then(InterceptorUtils.constant(ArrayUtils.clone(values))); return self(); Modified: commons/proper/proxy/branches/version-2.0-work/core/src/main/java/org/apache/commons/proxy2/stub/TrainingContext.java URL: http://svn.apache.org/viewvc/commons/proper/proxy/branches/version-2.0-work/core/src/main/java/org/apache/commons/proxy2/stub/TrainingContext.java?rev=1553232&r1=1553231&r2=1553232&view=diff ============================================================================== --- commons/proper/proxy/branches/version-2.0-work/core/src/main/java/org/apache/commons/proxy2/stub/TrainingContext.java (original) +++ commons/proper/proxy/branches/version-2.0-work/core/src/main/java/org/apache/commons/proxy2/stub/TrainingContext.java Tue Dec 24 00:08:43 2013 @@ -8,6 +8,7 @@ import org.apache.commons.proxy2.interce import org.apache.commons.proxy2.invoker.NullInvoker; import org.apache.commons.proxy2.invoker.RecordedInvocation; +import java.lang.reflect.Array; import java.lang.reflect.Method; import java.util.*; @@ -230,7 +231,14 @@ public class TrainingContext { frame.methodInvoked(method, arguments); } - return ProxyUtils.nullValue(method.getReturnType()); + + final Class<?> type = method.getReturnType(); + + if (Object[].class.isAssignableFrom(type)) + { + return Array.newInstance(type.getComponentType(), 0); + } + return ProxyUtils.nullValue(type); } } } Modified: commons/proper/proxy/branches/version-2.0-work/test/src/test/java/org/apache/commons/proxy2/stub/AbstractStubTestCase.java URL: http://svn.apache.org/viewvc/commons/proper/proxy/branches/version-2.0-work/test/src/test/java/org/apache/commons/proxy2/stub/AbstractStubTestCase.java?rev=1553232&r1=1553231&r2=1553232&view=diff ============================================================================== --- commons/proper/proxy/branches/version-2.0-work/test/src/test/java/org/apache/commons/proxy2/stub/AbstractStubTestCase.java (original) +++ commons/proper/proxy/branches/version-2.0-work/test/src/test/java/org/apache/commons/proxy2/stub/AbstractStubTestCase.java Tue Dec 24 00:08:43 2013 @@ -13,22 +13,22 @@ import static org.junit.Assert.*; public abstract class AbstractStubTestCase { -//---------------------------------------------------------------------------------------------------------------------- -// Fields -//---------------------------------------------------------------------------------------------------------------------- + // ---------------------------------------------------------------------------------------------------------------------- + // Fields + // ---------------------------------------------------------------------------------------------------------------------- protected ProxyFactory proxyFactory; protected StubInterface target; -//---------------------------------------------------------------------------------------------------------------------- -// Abstract Methods -//---------------------------------------------------------------------------------------------------------------------- + // ---------------------------------------------------------------------------------------------------------------------- + // Abstract Methods + // ---------------------------------------------------------------------------------------------------------------------- protected abstract StubInterface createProxy(Trainer<StubInterface> trainer); -//---------------------------------------------------------------------------------------------------------------------- -// Other Methods -//---------------------------------------------------------------------------------------------------------------------- + // ---------------------------------------------------------------------------------------------------------------------- + // Other Methods + // ---------------------------------------------------------------------------------------------------------------------- @Before public final void setUpProxyFactory() @@ -60,7 +60,8 @@ public abstract class AbstractStubTestCa @Override protected void train(StubInterface trainee) { - when(trainee.three(isInstance(String.class), "World")).thenAnswer(ObjectProviderUtils.constant("World")); + when(trainee.three(isInstance(String.class), "World")) + .thenAnswer(ObjectProviderUtils.constant("World")); } }); } @@ -87,6 +88,37 @@ public abstract class AbstractStubTestCa assertEquals("World", proxy.stub().one("Hello")); } + @Test + public void testStubArray() + { + final StubInterface proxy = createProxy(new Trainer<StubInterface>() + { + @Override + protected void train(StubInterface trainee) + { + when(trainee.stubs()).thenBuildArray().addElement(new Trainer<StubInterface>() + { + @Override + protected void train(StubInterface trainee) + { + when(trainee.one("Whatever")).thenReturn("Zero"); + } + }).addElement(new Trainer<StubInterface>() + { + @Override + protected void train(StubInterface trainee) + { + when(trainee.one("Whatever")).thenReturn("One"); + } + }) + .build(); + } + }); + + assertEquals("Zero", proxy.stubs()[0].one("Whatever")); + assertEquals("One", proxy.stubs()[1].one("Whatever")); + } + @Test(expected = IllegalStateException.class) public void testThenBeforeWhen() { @@ -152,7 +184,8 @@ public abstract class AbstractStubTestCa @Override protected void train(StubInterface trainee) { - when(trainee.one("Hello")).thenThrow(ObjectProviderUtils.constant(new RuntimeException("No way, Jose!"))); + when(trainee.one("Hello")).thenThrow( + ObjectProviderUtils.constant(new RuntimeException("No way, Jose!"))); } }); proxy.one("Hello"); @@ -219,7 +252,7 @@ public abstract class AbstractStubTestCa when(trainee.booleanArray()).thenReturn(false, true, false); } }); - assertTrue(Arrays.equals(new boolean[]{false, true, false}, proxy.booleanArray())); + assertTrue(Arrays.equals(new boolean[] { false, true, false }, proxy.booleanArray())); } @Test @@ -233,7 +266,7 @@ public abstract class AbstractStubTestCa when(trainee.byteArray()).thenReturn((byte) 1, (byte) 2); } }); - assertArrayEquals(new byte[]{1, 2}, proxy.byteArray()); + assertArrayEquals(new byte[] { 1, 2 }, proxy.byteArray()); } @Test @@ -247,7 +280,7 @@ public abstract class AbstractStubTestCa when(trainee.charArray()).thenReturn('a', 'b', 'c'); } }); - assertArrayEquals(new char[]{'a', 'b', 'c'}, proxy.charArray()); + assertArrayEquals(new char[] { 'a', 'b', 'c' }, proxy.charArray()); } @Test @@ -261,7 +294,7 @@ public abstract class AbstractStubTestCa when(trainee.doubleArray()).thenReturn(1.0, 2.0); } }); - assertArrayEquals(new double[]{1.0, 2.0}, proxy.doubleArray(), 0.0); + assertArrayEquals(new double[] { 1.0, 2.0 }, proxy.doubleArray(), 0.0); } @Test @@ -275,7 +308,7 @@ public abstract class AbstractStubTestCa when(trainee.floatArray()).thenReturn(1f, 2f); } }); - assertArrayEquals(new float[]{1f, 2f}, proxy.floatArray(), 0.0f); + assertArrayEquals(new float[] { 1f, 2f }, proxy.floatArray(), 0.0f); } @Test @@ -289,7 +322,7 @@ public abstract class AbstractStubTestCa when(trainee.intArray()).thenReturn(1, 2); } }); - assertArrayEquals(new int[]{1, 2}, proxy.intArray()); + assertArrayEquals(new int[] { 1, 2 }, proxy.intArray()); } @Test @@ -303,7 +336,7 @@ public abstract class AbstractStubTestCa when(trainee.longArray()).thenReturn(1, 2); } }); - assertArrayEquals(new long[]{1, 2}, proxy.longArray()); + assertArrayEquals(new long[] { 1, 2 }, proxy.longArray()); } @Test @@ -348,7 +381,7 @@ public abstract class AbstractStubTestCa when(trainee.shortArray()).thenReturn((short) 1, (short) 2); } }); - assertArrayEquals(new short[]{1, 2}, proxy.shortArray()); + assertArrayEquals(new short[] { 1, 2 }, proxy.shortArray()); } @Test @@ -378,6 +411,6 @@ public abstract class AbstractStubTestCa when(trainee.stringArray()).thenReturn("One", "Two"); } }); - assertArrayEquals(new String[]{"One", "Two"}, proxy.stringArray()); + assertArrayEquals(new String[] { "One", "Two" }, proxy.stringArray()); } } Modified: commons/proper/proxy/branches/version-2.0-work/test/src/test/java/org/apache/commons/proxy2/stub/StubBuilderTest.java URL: http://svn.apache.org/viewvc/commons/proper/proxy/branches/version-2.0-work/test/src/test/java/org/apache/commons/proxy2/stub/StubBuilderTest.java?rev=1553232&r1=1553231&r2=1553232&view=diff ============================================================================== --- commons/proper/proxy/branches/version-2.0-work/test/src/test/java/org/apache/commons/proxy2/stub/StubBuilderTest.java (original) +++ commons/proper/proxy/branches/version-2.0-work/test/src/test/java/org/apache/commons/proxy2/stub/StubBuilderTest.java Tue Dec 24 00:08:43 2013 @@ -222,6 +222,12 @@ public class StubBuilderTest extends Abs { return null; } + + @Override + public StubInterface[] stubs() + { + return new StubInterface[0]; + } } public interface Marker Modified: commons/proper/proxy/branches/version-2.0-work/test/src/test/java/org/apache/commons/proxy2/stub/StubInterface.java URL: http://svn.apache.org/viewvc/commons/proper/proxy/branches/version-2.0-work/test/src/test/java/org/apache/commons/proxy2/stub/StubInterface.java?rev=1553232&r1=1553231&r2=1553232&view=diff ============================================================================== --- commons/proper/proxy/branches/version-2.0-work/test/src/test/java/org/apache/commons/proxy2/stub/StubInterface.java (original) +++ commons/proper/proxy/branches/version-2.0-work/test/src/test/java/org/apache/commons/proxy2/stub/StubInterface.java Tue Dec 24 00:08:43 2013 @@ -23,23 +23,24 @@ public interface StubInterface // Other Methods //---------------------------------------------------------------------------------------------------------------------- - public String one(String value); - public String three(String arg1, String arg2); - public String two(String value); + String one(String value); + String three(String arg1, String arg2); + String two(String value); - public byte[] byteArray(); - public char[] charArray(); - public short[] shortArray(); - public int[] intArray(); - public long[] longArray(); - public float[] floatArray(); - public double[] doubleArray(); - public boolean[] booleanArray(); - public String[] stringArray(); + byte[] byteArray(); + char[] charArray(); + short[] shortArray(); + int[] intArray(); + long[] longArray(); + float[] floatArray(); + double[] doubleArray(); + boolean[] booleanArray(); + String[] stringArray(); - public String arrayParameter(String... strings); + String arrayParameter(String... strings); - public void voidMethod(String arg); + void voidMethod(String arg); - public StubInterface stub(); + StubInterface stub(); + StubInterface[] stubs(); }