001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.commons.proxy2.stub;
018
019import static org.junit.Assert.assertArrayEquals;
020import static org.junit.Assert.assertEquals;
021import static org.junit.Assert.assertNotNull;
022import static org.junit.Assert.assertTrue;
023
024import java.util.Arrays;
025
026import org.apache.commons.proxy2.AbstractProxyFactoryAgnosticTest;
027import org.apache.commons.proxy2.invoker.NullInvoker;
028import org.apache.commons.proxy2.provider.ObjectProviderUtils;
029import org.junit.Before;
030import org.junit.Test;
031
032public abstract class AbstractStubTestCase extends AbstractProxyFactoryAgnosticTest
033{
034    // *****************************************************************************************************************
035    // Fields
036    // *****************************************************************************************************************
037
038    protected StubInterface target;
039
040    // *****************************************************************************************************************
041    // Abstract Methods
042    // *****************************************************************************************************************
043
044    protected abstract StubInterface createProxy(Trainer<StubInterface> trainer);
045
046    // *****************************************************************************************************************
047    // Other Methods
048    // *****************************************************************************************************************
049
050    @Before
051    public final void setUpProxyFactory()
052    {
053        this.target = proxyFactory.createInvokerProxy(NullInvoker.INSTANCE, StubInterface.class);
054    }
055
056    @Test
057    public void testAnyMatcher()
058    {
059        final StubInterface proxy = createProxy(new Trainer<StubInterface>()
060        {
061            @Override
062            protected void train(StubInterface trainee)
063            {
064                when(trainee.one(any(String.class))).thenReturn("World");
065            }
066        });
067        assertEquals("World", proxy.one("Hello"));
068        assertEquals("World", proxy.one(null));
069    }
070
071    @Test(expected = IllegalStateException.class)
072    public void testMixingArgumentMatchingStrategies()
073    {
074        createProxy(new Trainer<StubInterface>()
075        {
076            @Override
077            protected void train(StubInterface trainee)
078            {
079                when(trainee.three(isInstance(String.class), "World"))
080                        .thenAnswer(ObjectProviderUtils.constant("World"));
081            }
082        });
083    }
084
085    @Test
086    public void testStubReturn()
087    {
088        final StubInterface proxy = createProxy(new Trainer<StubInterface>()
089        {
090            @Override
091            protected void train(StubInterface trainee)
092            {
093                when(trainee.stub()).thenStub(new Trainer<StubInterface>()
094                {
095                    @Override
096                    protected void train(StubInterface trainee)
097                    {
098                        when(trainee.one("Hello")).thenReturn("World");
099                    }
100                });
101            }
102        });
103        assertNotNull(proxy.stub());
104        assertEquals("World", proxy.stub().one("Hello"));
105    }
106
107    @Test
108    public void testStubArray()
109    {
110        final StubInterface proxy = createProxy(new Trainer<StubInterface>()
111        {
112            @Override
113            protected void train(StubInterface trainee)
114            {
115                when(trainee.stubs()).thenBuildArray().addElement(new Trainer<StubInterface>()
116                {
117                    @Override
118                    protected void train(StubInterface trainee)
119                    {
120                        when(trainee.one("Whatever")).thenReturn("Zero");
121                    }
122                }).addElement(new Trainer<StubInterface>()
123                {
124                    @Override
125                    protected void train(StubInterface trainee)
126                    {
127                        when(trainee.one("Whatever")).thenReturn("One");
128                    }
129                }).build();
130            }
131        });
132
133        assertEquals("Zero", proxy.stubs()[0].one("Whatever"));
134        assertEquals("One", proxy.stubs()[1].one("Whatever"));
135    }
136
137    @Test(expected = IllegalStateException.class)
138    public void testThenBeforeWhen()
139    {
140        createProxy(new Trainer<StubInterface>()
141        {
142            @Override
143            protected void train(StubInterface trainee)
144            {
145                thenThrow(new RuntimeException("Oops!"));
146            }
147        });
148    }
149
150    @Test(expected = IllegalArgumentException.class)
151    public void testThrowExceptionWithException()
152    {
153        StubInterface proxy = createProxy(new Trainer<StubInterface>()
154        {
155            @Override
156            protected void train(StubInterface trainee)
157            {
158                trainee.voidMethod("Hello");
159                thenThrow(new IllegalArgumentException("Nope!"));
160            }
161        });
162        proxy.voidMethod("Hello");
163    }
164
165    @Test(expected = IllegalArgumentException.class)
166    public void testThrowExceptionWithProvidedException()
167    {
168        StubInterface proxy = createProxy(new Trainer<StubInterface>()
169        {
170            @Override
171            protected void train(StubInterface trainee)
172            {
173                trainee.voidMethod("Hello");
174                thenThrow(ObjectProviderUtils.constant(new IllegalArgumentException("Nope!")));
175            }
176        });
177        proxy.voidMethod("Hello");
178    }
179
180    @Test(expected = RuntimeException.class)
181    public void testThrowingExceptionObject()
182    {
183        final StubInterface proxy = createProxy(new Trainer<StubInterface>()
184        {
185            @Override
186            protected void train(StubInterface trainee)
187            {
188                when(trainee.one("Hello")).thenThrow(new RuntimeException("No way, Jose!"));
189            }
190        });
191        proxy.one("Hello");
192    }
193
194    @Test(expected = RuntimeException.class)
195    public void testThrowingProvidedException()
196    {
197        final StubInterface proxy = createProxy(new Trainer<StubInterface>()
198        {
199            @Override
200            protected void train(StubInterface trainee)
201            {
202                when(trainee.one("Hello")).thenThrow(
203                        ObjectProviderUtils.constant(new RuntimeException("No way, Jose!")));
204            }
205        });
206        proxy.one("Hello");
207    }
208
209    @Test(expected = IllegalStateException.class)
210    public void testUsingWrongStub()
211    {
212        createProxy(new Trainer<StubInterface>()
213        {
214            @Override
215            protected void train(final StubInterface parent)
216            {
217                when(parent.stub()).thenStub(new Trainer<StubInterface>()
218                {
219                    @Override
220                    protected void train(final StubInterface child)
221                    {
222                        when(parent.one("Hello")).thenReturn("World");
223                    }
224                });
225            }
226        });
227    }
228
229    @Test
230    public void testWithArgumentMatchers()
231    {
232        final StubInterface proxy = createProxy(new Trainer<StubInterface>()
233        {
234            @Override
235            protected void train(StubInterface trainee)
236            {
237                when(trainee.one(isInstance(String.class))).thenAnswer(ObjectProviderUtils.constant("World"));
238            }
239        });
240        assertEquals("World", proxy.one("Hello"));
241        assertEquals("World", proxy.one("Whatever"));
242    }
243
244    @Test
245    public void testWithArrayParameter()
246    {
247        StubInterface proxy = createProxy(new Trainer<StubInterface>()
248        {
249            @Override
250            protected void train(StubInterface trainee)
251            {
252                when(trainee.arrayParameter("One", "Two", "Three")).thenReturn("Four");
253            }
254        });
255
256        assertEquals("Four", proxy.arrayParameter("One", "Two", "Three"));
257    }
258
259    @Test
260    public void testWithBooleanArray()
261    {
262        final StubInterface proxy = createProxy(new Trainer<StubInterface>()
263        {
264            @Override
265            protected void train(StubInterface trainee)
266            {
267                when(trainee.booleanArray()).thenReturn(false, true, false);
268            }
269        });
270        assertTrue(Arrays.equals(new boolean[] { false, true, false }, proxy.booleanArray()));
271    }
272
273    @Test
274    public void testWithByteArray()
275    {
276        final StubInterface proxy = createProxy(new Trainer<StubInterface>()
277        {
278            @Override
279            protected void train(StubInterface trainee)
280            {
281                when(trainee.byteArray()).thenReturn((byte) 1, (byte) 2);
282            }
283        });
284        assertArrayEquals(new byte[] { 1, 2 }, proxy.byteArray());
285    }
286
287    @Test
288    public void testWithCharArray()
289    {
290        final StubInterface proxy = createProxy(new Trainer<StubInterface>()
291        {
292            @Override
293            protected void train(StubInterface trainee)
294            {
295                when(trainee.charArray()).thenReturn('a', 'b', 'c');
296            }
297        });
298        assertArrayEquals(new char[] { 'a', 'b', 'c' }, proxy.charArray());
299    }
300
301    @Test
302    public void testWithDoubleArray()
303    {
304        final StubInterface proxy = createProxy(new Trainer<StubInterface>()
305        {
306            @Override
307            protected void train(StubInterface trainee)
308            {
309                when(trainee.doubleArray()).thenReturn(1.0, 2.0);
310            }
311        });
312        assertArrayEquals(new double[] { 1.0, 2.0 }, proxy.doubleArray(), 0.0);
313    }
314
315    @Test
316    public void testWithFloatArray()
317    {
318        final StubInterface proxy = createProxy(new Trainer<StubInterface>()
319        {
320            @Override
321            protected void train(StubInterface trainee)
322            {
323                when(trainee.floatArray()).thenReturn(1f, 2f);
324            }
325        });
326        assertArrayEquals(new float[] { 1f, 2f }, proxy.floatArray(), 0.0f);
327    }
328
329    @Test
330    public void testWithIntArray()
331    {
332        final StubInterface proxy = createProxy(new Trainer<StubInterface>()
333        {
334            @Override
335            protected void train(StubInterface trainee)
336            {
337                when(trainee.intArray()).thenReturn(1, 2);
338            }
339        });
340        assertArrayEquals(new int[] { 1, 2 }, proxy.intArray());
341    }
342
343    @Test
344    public void testWithLongArray()
345    {
346        final StubInterface proxy = createProxy(new Trainer<StubInterface>()
347        {
348            @Override
349            protected void train(StubInterface trainee)
350            {
351                when(trainee.longArray()).thenReturn(1, 2);
352            }
353        });
354        assertArrayEquals(new long[] { 1, 2 }, proxy.longArray());
355    }
356
357    @Test
358    public void testWithMismatchedArgument()
359    {
360        final StubInterface proxy = createProxy(new Trainer<StubInterface>()
361        {
362            @Override
363            protected void train(StubInterface trainee)
364            {
365                when(trainee.one(eq("Hello"))).thenReturn("World");
366            }
367        });
368        assertEquals("World", proxy.one("Hello"));
369        assertEquals(null, proxy.one("Whatever"));
370    }
371
372    @Test
373    public void testWithMultipleMethodsTrained()
374    {
375        final StubInterface proxy = createProxy(new Trainer<StubInterface>()
376        {
377            @Override
378            protected void train(StubInterface trainee)
379            {
380                when(trainee.one("Hello")).thenReturn("World");
381                when(trainee.two("Foo")).thenReturn("Bar");
382            }
383        });
384        assertEquals("World", proxy.one("Hello"));
385        assertEquals("Bar", proxy.two("Foo"));
386    }
387
388    @Test
389    public void testWithShortArray()
390    {
391        final StubInterface proxy = createProxy(new Trainer<StubInterface>()
392        {
393            @Override
394            protected void train(StubInterface trainee)
395            {
396                when(trainee.shortArray()).thenReturn((short) 1, (short) 2);
397            }
398        });
399        assertArrayEquals(new short[] { 1, 2 }, proxy.shortArray());
400    }
401
402    @Test
403    public void testWithSingleMethodTrained()
404    {
405        final StubInterface proxy = createProxy(new Trainer<StubInterface>()
406        {
407            @Override
408            protected void train(StubInterface trainee)
409            {
410                when(trainee.one("Hello")).thenReturn("World");
411            }
412        });
413        assertEquals("World", proxy.one("Hello"));
414        assertEquals(null, proxy.two("Whatever"));
415        assertEquals(null, proxy.one("Mismatch!"));
416    }
417
418    @Test
419    public void testWithStringArray()
420    {
421        final StubInterface proxy = createProxy(new Trainer<StubInterface>()
422        {
423            @Override
424            protected void train(StubInterface trainee)
425            {
426                when(trainee.stringArray()).thenReturn("One", "Two");
427            }
428        });
429        assertArrayEquals(new String[] { "One", "Two" }, proxy.stringArray());
430    }
431
432    /*
433     * This test replicates #thenStub() functionality in a more "ignorant" (ergo versatile) manner.
434     */
435    @Test
436    public void testInterruptResume()
437    {
438        final StubInterface proxy = createProxy(new Trainer<StubInterface>()
439        {
440            @Override
441            protected void train(StubInterface trainee)
442            {
443                when(trainee.stub()).thenReturn(createProxy(new Trainer<StubInterface>()
444                {
445                    @Override
446                    protected void train(StubInterface trainee)
447                    {
448                        when(trainee.one("Hello")).thenReturn("World");
449                    }
450                }));
451            }
452        });
453        assertNotNull(proxy.stub());
454        assertEquals("World", proxy.stub().one("Hello"));
455    }
456}