1   // Copyright (c) 2003, Chad Woolley, All rights reserved.
2   
3   package org.virtualmock.call;
4   
5   import junit.framework.Test;
6   import junit.framework.TestCase;
7   import org.easymock.MockControl;
8   import org.hansel.CoverageDecorator;
9   import org.virtualmock.call.InvokedCall;
10  import org.virtualmock.call.RecordedCall;
11  import org.virtualmock.call.Signature;
12  import org.virtualmock.matcher.AlwaysMatcher;
13  import org.virtualmock.matcher.ArgMatcher;
14  
15  
16  /***
17   * Tests the RecordedCall class
18   *
19   * @author Chad Woolley
20   * @version $Revision: 1.2 $
21   */
22  public class RecordedCallTest extends TestCase {
23      Class classType = null;
24      Integer argValue2 = null;
25      Object returnValue = null;
26      RecordedCall call = null;
27      Signature signature = null;
28      Signature signatureNoArgs = null;
29      String argValue1 = null;
30      String className = null;
31      String methodName = null;
32      Throwable exception = null;
33      ArgMatcher[] argMatchers = null;
34      Class[] argTypes = null;
35      Object[] argValues = null;
36  
37      /***
38       * Set up the test
39       *
40       * @throws Exception any exception thrown during setup.
41       */
42      public void setUp() throws Exception {
43          super.setUp();
44          classType = RecordedCall.class;
45          className = "org.virtualmock.call.RecordedCall";
46          methodName = "MyMethod";
47          argTypes = new Class[] {String.class, Integer.class};
48          argValue1 = "ARG0";
49          argValue2 = new Integer(1);
50          argValues = new Object[] {argValue1, argValue2};
51          returnValue = "RETURN_VALUE";
52          signature =
53              new Signature(returnValue.getClass(), classType, methodName,
54                  argTypes);
55          signatureNoArgs =
56              new Signature(returnValue.getClass(), classType, methodName);
57          exception = new RuntimeException("EXCEPTION");
58      }
59  
60      /***
61       * Hansel support
62       *
63       * @return the decorated Test
64       */
65      public static Test suite() {
66          CoverageDecorator cd =
67              new CoverageDecorator(RecordedCallTest.class,
68                  new Class[] {RecordedCall.class});
69          cd.setDisplayStatistics(true);
70  
71          return cd;
72      }
73  
74      /***
75       * Tear down the test
76       *
77       * @throws Exception any exception thrown during teardown.
78       */
79      public void tearDown() throws Exception {
80          super.tearDown();
81      }
82  
83      /***
84       * Test the ArgMatcher accessors
85       */
86      public void testArgMatcherAccessors() {
87          call = new RecordedCall(signature, argValues, exception);
88          argMatchers = new ArgMatcher[2];
89          argMatchers[0] = new AlwaysMatcher();
90          argMatchers[1] = new AlwaysMatcher();
91          call.setArgMatchers(argMatchers);
92          assertEquals(2, call.getArgMatchers().length);
93      }
94  
95      /***
96       * Test that the setArgMatchers() method throws an exception if the number
97       * of matchers doesn't match the number of arguments
98       */
99      public void testArgMatcherIncorrectCountThrowsException() {
100         RecordedCall recordedCall = new RecordedCall(signature, argValues);
101         ArgMatcher[] argMatchers = new ArgMatcher[] {new AlwaysMatcher()};
102 
103         try {
104             recordedCall.setArgMatchers(argMatchers);
105             fail("expected exception");
106         } catch (IllegalArgumentException e) {
107         }
108     }
109 
110     /***
111      * Tests constructor with Signature as argument
112      */
113     public void testConstructorWithSignatureAsArgWorks() {
114         call = new RecordedCall(signatureNoArgs);
115         assertEquals(signatureNoArgs, call.getSignature());
116     }
117 
118     /***
119      * Test that the hasMatchingArgs() method fails with the default
120      * ArgMatchers
121      */
122     public void testHasMatchingArgsWithDefaultArgMatcherReturnsFalse() {
123         RecordedCall recordedCall =
124             new RecordedCall(signature, argValues, exception);
125         String newArgValue1 = "NEW ARG0";
126         Integer newArgValue2 = new Integer(-1);
127         Object[] newArgValues = new Object[] {newArgValue1, newArgValue2};
128         InvokedCall invokedCall =
129             new InvokedCall(signature, newArgValues, exception);
130 
131         // NOTE: this cannot mock up EqualsMatcher, because it is instantiated
132         boolean hasMatchingArgs = recordedCall.hasMatchingArgs(invokedCall);
133 
134         assertFalse(hasMatchingArgs);
135 
136         boolean matches = recordedCall.matches(invokedCall);
137         assertFalse(matches);
138     }
139 
140     /***
141      * Test that the hasMatchingArgs() method works if no ArgMatchers are
142      * defined
143      */
144     public void testHasMatchingArgsWithDefaultArgMatcherReturnsTrue() {
145         RecordedCall recordedCall =
146             new RecordedCall(signature, argValues, exception);
147         InvokedCall invokedCall =
148             new InvokedCall(signature, argValues, exception);
149 
150         // NOTE: this cannot mock up EqualsMatcher, because it is instantiated
151         boolean hasMatchingArgs = recordedCall.hasMatchingArgs(invokedCall);
152 
153         assertTrue(hasMatchingArgs);
154     }
155 
156     /***
157      * Test that the invocationCount works
158      */
159     public void testIncrementInvocationCountWorks() {
160         call = new RecordedCall(signature, argValues, returnValue);
161         call.incrementInvocationCount();
162         assertEquals(1, call.getInvocationCount());
163     }
164 
165     /***
166      * Test that isInvocable returns false if this call has unlimited
167      * invocations and has already been invoked.
168      */
169     public void testIsInvocableReturnsFalseIfCallDoesNotHaveUnlimitedInvocationsAndHasBeenInvoked() {
170         call = new RecordedCall(signature, argValues, exception);
171         call.setUnlimitedInvocations(false);
172         call.incrementInvocationCount();
173         assertFalse(call.isInvocable());
174     }
175 
176     /***
177      * Test that isInvocable returns true if this call has unlimited
178      * invocations.
179      */
180     public void testIsInvocableReturnsTrueIfCallHasUnlimitedInvocations() {
181         call = new RecordedCall(signature, argValues, exception);
182         call.setUnlimitedInvocations(true);
183         assertTrue(call.isInvocable());
184     }
185 
186     /***
187      * Test that isInvocable returns true if this call has not yet been
188      * invoked.
189      */
190     public void testIsInvocableReturnsTrueIfCallIsNotInvoked() {
191         call = new RecordedCall(signature, argValues, exception);
192         assertTrue(call.isInvocable());
193     }
194 
195     /***
196      * Test that the invocationCount returns false if the call was not invoked
197      */
198     public void testIsInvokedReturnsFalseIfNotInvoked() {
199         call = new RecordedCall(signature, argValues, exception);
200         assertFalse(call.isInvoked());
201     }
202 
203     /***
204      * Test that the invocationCount returns true if the call was invoked
205      */
206     public void testIsInvokedReturnsTrueIfInvoked() {
207         call = new RecordedCall(signature, argValues, exception);
208         call.incrementInvocationCount();
209         assertTrue(call.isInvoked());
210     }
211 
212     /***
213      * Test that the matches() method throws an exception if the signatures
214      * don't match
215      */
216     public void testMatchWithIncompatibleSignaturesThrowsException() {
217         RecordedCall recordedCall = new RecordedCall(signature, argValues);
218         Signature differentSignature =
219             new Signature(returnValue.getClass(), Object.class, "someMethod",
220                 new Class[0]);
221         InvokedCall invokedCall =
222             new InvokedCall(differentSignature, new Object[0]);
223 
224         try {
225             recordedCall.hasMatchingArgs(invokedCall);
226             fail("expected exception");
227         } catch (IllegalArgumentException e) {
228         }
229     }
230 
231     /***
232      * Test that the matches() method works.
233      *
234      * @todo deleting this test only causes one Hansel coverage error.  It
235      *       could probably be greatly simplified to provide the same
236      *       coverage.
237      */
238     public void testMatches() {
239         RecordedCall recordedCall =
240             new RecordedCall(signature, argValues, exception);
241         InvokedCall invokedCall =
242             new InvokedCall(signature, argValues, exception);
243 
244         // set up the EasyMock mock and control
245         ArgMatcher mockArgMatcher = null;
246         MockControl controlArgMatcher =
247             MockControl.createControl(ArgMatcher.class);
248         mockArgMatcher = (ArgMatcher) controlArgMatcher.getMock();
249 
250         // record the expected calls to ArgMatcher.matches()
251         // record two invocations, one for each parameter, with true returned each time
252         mockArgMatcher.matches(argValue1, argValue1);
253         controlArgMatcher.setReturnValue(true);
254         mockArgMatcher.matches(argValue2, argValue2);
255         controlArgMatcher.setReturnValue(true);
256         recordedCall.setArgMatchers(new ArgMatcher[] {
257                 mockArgMatcher, mockArgMatcher
258             });
259         controlArgMatcher.replay();
260 
261         boolean matches = recordedCall.hasMatchingArgs(invokedCall);
262         controlArgMatcher.verify();
263         assertTrue(matches);
264     }
265 
266     /***
267      * Test that the matches method returns false non-matching argvalues
268      */
269     public void testMatchesReturnsFalseWithNonMatchingArgValues() {
270         RecordedCall recordedCall =
271             new RecordedCall(signature, argValues, exception);
272         Object[] argValues2 = new Object[] {"XXX", argValue2};
273         InvokedCall invokedCall =
274             new InvokedCall(signature, argValues2, exception);
275 
276         boolean matches = recordedCall.matches(invokedCall);
277 
278         assertFalse(matches);
279     }
280 
281     /***
282      * Test that the matches method returns false with non-matching signatures
283      */
284     public void testMatchesReturnsFalseWithNonMatchingSignatures() {
285         RecordedCall recordedCall =
286             new RecordedCall(signature, argValues, exception);
287         Signature signature2 = new Signature(classType, methodName);
288         InvokedCall invokedCall = new InvokedCall(signature2);
289 
290         boolean matches = recordedCall.matches(invokedCall);
291 
292         assertFalse(matches);
293     }
294 
295     /***
296      * Test that the matches method returns true with matching signatures and
297      * argvalues
298      */
299     public void testMatchesReturnsTrueWithMatchingSignaturesAndArgValues() {
300         RecordedCall recordedCall =
301             new RecordedCall(signature, argValues, exception);
302         InvokedCall invokedCall =
303             new InvokedCall(signature, argValues, exception);
304 
305         boolean matches = recordedCall.matches(invokedCall);
306 
307         assertTrue(matches);
308     }
309 
310     /***
311      * Test that the unlimitedInvocations flag works
312      */
313     public void testUnlimitedInvocationsFlagWorks() {
314         call = new RecordedCall(signature, argValues, exception);
315         call.setUnlimitedInvocations(true);
316         assertTrue(call.hasUnlimitedInvocations());
317     }
318 }