1 | package biz.xsoftware.mock.client; |
2 | |
3 | import java.util.ArrayList; |
4 | import java.util.HashMap; |
5 | import java.util.HashSet; |
6 | import java.util.List; |
7 | import java.util.Map; |
8 | import java.util.Set; |
9 | |
10 | |
11 | /** |
12 | * This is a super class for mock Objects. It has the following options |
13 | * <ol> |
14 | * <li>Guarantee order of events and that events happen on one object</li> |
15 | * <li>Guarantee events called with order not mattering on one object</li> |
16 | * <li>Guarantee order of events is correct between two objects(One mock obj. implements two interfaces)</li> |
17 | * </ol> |
18 | * This class will also return the parameters that were passed into the MockObject |
19 | * so they can be introspected in testing to make sure they were correct. |
20 | * |
21 | * The MockObject extending this class can also be told to throw exceptions on certain |
22 | * methods so we can test error leg behavior. |
23 | * |
24 | * Example of how to use |
25 | * MockActionListener implements ActionListener and extends this class |
26 | * The only method in MockActionListener |
27 | * is |
28 | * <PRE> |
29 | * public final static ACTION_METHOD = "actionPerformed method"; |
30 | * public void actionPerformed(ActionEvent evt) { |
31 | * super.methodCalled(ACTION_METHOD, evt); |
32 | * } |
33 | * </PRE> |
34 | * |
35 | * In the test, when you expect an ActionEvent, you can call |
36 | * <PRE> |
37 | * Object o = MockActionListener.expectEvent(ACTION_METHOD); |
38 | * ActionEvent evt = (ActionEvent)evt; |
39 | * assertNonNull(evt.getSource()); |
40 | * </PRE> |
41 | * |
42 | * Another useful behavior is throwing any type of exception using |
43 | * setExceptionOnMethod(String method, Throwable e). This can test |
44 | * robustness in a system to make sure listeners or services that |
45 | * throw exceptions don't affect your system, or at least affect |
46 | * your system in the proper way. |
47 | * |
48 | * @author Dean Hiller (dean@xsoftware.biz) |
49 | */ |
50 | public abstract class JsMockSuperclass implements JsMockObject { |
51 | |
52 | /** |
53 | * List of the current methods that have been called. |
54 | */ |
55 | private List methodsCalled = new ArrayList(); |
56 | |
57 | /** |
58 | * A map of queues, containing either |
59 | * 1. objects to return when methods are called |
60 | * 2. Behaviors to run which return objects to return |
61 | * 3. Exceptions to throw |
62 | */ |
63 | private Map methodToReturnVal = new HashMap(); |
64 | /** |
65 | * A map of default return values, which are used to return if the |
66 | * queue for the method is empty. |
67 | */ |
68 | private Map methodToDefaultRetVal = new HashMap(); |
69 | |
70 | private List ignoredMethods = new ArrayList(); |
71 | |
72 | /** |
73 | * Default wait time to wait for a method to be called once expectCall is |
74 | * called. |
75 | */ |
76 | public static final int DEFAULT_WAIT_TIME = 10000; |
77 | private int waitTime = DEFAULT_WAIT_TIME; |
78 | |
79 | private String id; |
80 | |
81 | /** |
82 | * Default constructor of superclass of all mockObjects with a delay of |
83 | * 10 seconds. This delay is the amount of time the mock object waits for |
84 | * a method to be called when a client calls expectCall. |
85 | */ |
86 | public JsMockSuperclass() { |
87 | } |
88 | /** |
89 | * The constructor to use to override the default delay({@link #DEFAULT_WAIT_TIME}) |
90 | * such that the mock object will give methods a longer time to be called |
91 | * before timing out to fail the test. |
92 | * |
93 | * @param delay The amount of time in milliseconds to wait for a method to be |
94 | * called. |
95 | */ |
96 | public JsMockSuperclass(int delay) { |
97 | waitTime = delay; |
98 | } |
99 | |
100 | public JsMockSuperclass(String id) { |
101 | this.id = id; |
102 | } |
103 | |
104 | public void setExpectTimeout(int delay) { |
105 | this.waitTime = delay; |
106 | } |
107 | public int getExpectTimeout() { |
108 | return waitTime; |
109 | } |
110 | |
111 | public void addIgnore(String method) |
112 | { |
113 | ignoreImpl(new String[] {method}); |
114 | } |
115 | |
116 | public void removeIgnore(String method) |
117 | { |
118 | removeIgnoreImpl(new String[] {method}); |
119 | } |
120 | |
121 | private void removeIgnoreImpl(String[] methods) |
122 | { |
123 | for(int i = 0; i < methods.length; i++) |
124 | { |
125 | String method = methods[i]; |
126 | ignoredMethods.remove(method); |
127 | } |
128 | } |
129 | |
130 | private void ignoreImpl(String[] methods) |
131 | { |
132 | addIgnoredMethods(methods); |
133 | } |
134 | |
135 | private void addIgnoredMethods(String[] methods) { |
136 | if(methods == null) |
137 | return; |
138 | verifyMethodsExist(methods); |
139 | |
140 | for(int i = 0; i < methods.length; i++) |
141 | { |
142 | String method = methods[i]; |
143 | ignoredMethods.add(method); |
144 | } |
145 | } |
146 | |
147 | /** |
148 | * Subclasses should call this method when a method on their interface |
149 | * is called. This method is for users to create subclasses and call so |
150 | * they don't have to wrap it in a try-catch block. |
151 | * |
152 | * @param method |
153 | * @param parameters |
154 | * @return whatever the client has specified using addReturnValue |
155 | */ |
156 | protected Object methodCalled(String method, Object p) { |
157 | try { |
158 | Object parameters = p; |
159 | if(!(parameters instanceof Object[])) { |
160 | parameters = new Object[] {parameters}; |
161 | } |
162 | return methodCalledImpl(method, (Object[])parameters); |
163 | } catch (Throwable e) { |
164 | if(e instanceof RuntimeException) |
165 | throw (RuntimeException)e; |
166 | throw new RuntimeException("Sorry, must wrap exception, unwrap in " + |
167 | "your mockobject, or have mockObject call methodCalledImpl instead", e); |
168 | } |
169 | } |
170 | |
171 | protected synchronized Object methodCalledImpl(String method, Object[] parameters) throws Throwable { |
172 | //Since no notify and wait can be used in GWT mocklib, intern is not needed and can be commented out. |
173 | // method = method.intern(); |
174 | String params = ""; |
175 | if(parameters == null) { |
176 | params = "no params"; |
177 | } else { |
178 | Object[] array = parameters; |
179 | for(int i = 0; i < array.length-1; i++) { |
180 | params += array[i]+", "; |
181 | } |
182 | params += array[array.length-1]; |
183 | } |
184 | |
185 | System.out.println(id+"method called="+method+"("+params+") on obj="+this); |
186 | |
187 | //sometimes, the contract is for the "code" to give a parameter |
188 | //to a library and then modify the parameter after the library |
189 | //is done with it. This means the object the "code" gave to |
190 | //the MockObject will change out from under the MockObject and be |
191 | //corrupted meaning you can't write a test to test the contract |
192 | //without cloning the object so it can't be changed. |
193 | Object[] newParams = clone(method, parameters); |
194 | methodsCalled.add(new JsCalledMethod(method, newParams, new Throwable().fillInStackTrace())); |
195 | |
196 | // this.notifyAll(); |
197 | |
198 | return findNextAction(method, parameters); |
199 | } |
200 | |
201 | private Object findNextAction(String method, Object[] params) throws Throwable { |
202 | List l = (List)methodToReturnVal.get(method); |
203 | if(l == null) |
204 | { |
205 | return methodToDefaultRetVal.get(method); |
206 | } |
207 | |
208 | Object retVal = l.remove(0); |
209 | if(l.size()<=0) |
210 | methodToReturnVal.remove(method); |
211 | else if(retVal == null) |
212 | methodToDefaultRetVal.get(method); |
213 | |
214 | if(retVal instanceof JsBehavior) { |
215 | return ((JsBehavior)retVal).runMethod(params); |
216 | } else if(retVal instanceof Throwable) { |
217 | Throwable t = (Throwable)retVal; |
218 | t.fillInStackTrace(); |
219 | throw t; |
220 | } else |
221 | return retVal; |
222 | } |
223 | |
224 | // /** |
225 | // * @see biz.xsoftware.mock.JsMockObject#expectUnorderedCalls(java.lang.String[]) |
226 | // */ |
227 | // public synchronized JsCalledMethod[] expectUnorderedCalls(String[] methods) { |
228 | // if(methods == null) |
229 | // throw new IllegalArgumentException("methods cannot be null"); |
230 | // else if(methods.length <= 0) |
231 | // throw new IllegalArgumentException("methods.length must be >= 1"); |
232 | // for(int i = 0; i < methods.length; i++) { |
233 | // if(methods[i] == null) |
234 | // throw new IllegalArgumentException("None of values in methods " + |
235 | // "can be null, yet methods["+i+"] was null"); |
236 | // } |
237 | // |
238 | // Map expectedMethods = new HashMap(); |
239 | // for(int i = 0; i < methods.length; i++) { |
240 | // expectedMethods.put(methods[i], new Integer(i)); |
241 | // } |
242 | // |
243 | // Set ignorables = createIgnorableMap(ignoredMethods); |
244 | // JsCalledMethod[] retVal = new JsCalledMethod[methods.length]; |
245 | // |
246 | // List methodsCalledList = new ArrayList(); |
247 | // for(int i = 0; i < methods.length; i++) { |
248 | // if(ANY.equals(methods[i])) |
249 | // throw new IllegalArgumentException("The parameter 'methods' in " + |
250 | // "expectUnorderedCalls cannot contain MockSuperclass.ANY(use expectOrderedCalls instead)"); |
251 | // |
252 | // JsCalledMethod o = expectUnignoredCall(ANY, ignorables, methodsCalledList); |
253 | // if(o == null) { |
254 | // String reason = putTogetherReason(methods, ignorables, methodsCalledList, |
255 | // "timed out on next expected method\n"); |
256 | // throw new JsExpectFailedException("Timed out waiting for a method call\n" |
257 | // +reason, retVal, JsExpectFailedException.TIMED_OUT); |
258 | // } |
259 | // Integer index = (Integer)expectedMethods.remove(o.getMethodName()); |
260 | // if(index == null) { |
261 | // String reason = putTogetherReason(methods, ignorables, methodsCalledList, null); |
262 | // throw new JsExpectFailedException(reason, retVal, JsExpectFailedException.UNEXPECTED_CALL_BEFORE); |
263 | // } |
264 | // |
265 | // retVal[index.intValue()] = o; |
266 | // } |
267 | // |
268 | // LeftOverMethods leftOver = getLeftOverMethods(ignorables); |
269 | // if(leftOver != null) { |
270 | // String reason = putTogetherReason(methods, ignorables, methodsCalledList, "extra method(s)="+leftOver+"\n"); |
271 | // throw new JsExpectFailedException("There was a method called after your expected methods.\n"+reason, retVal |
272 | // , JsExpectFailedException.UNEXPECTED_CALL_AFTER); |
273 | // } |
274 | // |
275 | // return retVal; |
276 | // } |
277 | |
278 | private String getHowMethodWasCalled(JsCalledMethod method) { |
279 | // Throwable t = method.getHowItWasCalled(); |
280 | String retVal = "\nThe last method was="+method.getMethodName(); |
281 | retVal += "\nHere is a stack trace showing "; |
282 | retVal += "you how it was called...\n"; |
283 | retVal += "--------BEGIN="+method.getMethodName()+"---------------\n"; |
284 | retVal += "THIS DOES NOT WORK IN GWT(so it is commented out)\n"; |
285 | // StringWriter s = new StringWriter(); |
286 | // PrintWriter p = new PrintWriter(s); |
287 | // t.printStackTrace(p); |
288 | // retVal += s.toString(); |
289 | retVal += "--------END="+method.getMethodName() +"---------------\n"; |
290 | return retVal; |
291 | } |
292 | |
293 | private JsCalledMethod[] cleanup(JsCalledMethod[] methods, int size) { |
294 | JsCalledMethod[] retVal = new JsCalledMethod[size]; |
295 | for(int i = 0; i < retVal.length; i++) { |
296 | retVal[i] = methods[i]; |
297 | } |
298 | return retVal; |
299 | } |
300 | |
301 | /** |
302 | * @see biz.xsoftware.mock.JsMockObject#expect(java.lang.String) |
303 | */ |
304 | public JsCalledMethod expect(String method) { |
305 | return expectImpl(new String[] {method})[0]; |
306 | } |
307 | |
308 | /** |
309 | * @see biz.xsoftware.mock.JsMockObject#expect(java.lang.String[]) |
310 | */ |
311 | public synchronized JsCalledMethod[] expect(String[] methods) |
312 | { |
313 | return expectImpl(methods); |
314 | } |
315 | |
316 | private synchronized JsCalledMethod[] expectImpl(String[] methods) |
317 | { |
318 | return expectOrderedCalls(methods); |
319 | } |
320 | |
321 | /** |
322 | * @see biz.xsoftware.mock.JsMockObject#expectOrderedCalls(java.lang.String[]) |
323 | */ |
324 | private synchronized JsCalledMethod[] expectOrderedCalls(String[] methods) { |
325 | if(methods == null) |
326 | throw new IllegalArgumentException("methods cannot be null"); |
327 | else if(methods.length <= 0) |
328 | throw new IllegalArgumentException("methods.length must be >= 1"); |
329 | for(int i = 0; i < methods.length; i++) { |
330 | if(methods[i] == null) |
331 | throw new IllegalArgumentException("None of values in methods can be null, yet methods["+i+"] was null"); |
332 | } |
333 | |
334 | verifyMethodsExist(methods); |
335 | |
336 | Set ignorables = createIgnorableMap(ignoredMethods); |
337 | |
338 | List methodsCalledList = new ArrayList(); |
339 | JsCalledMethod[] retVal = new JsCalledMethod[methods.length]; |
340 | int i = 0; |
341 | for(; i < methods.length; i++) { |
342 | String method = methods[i]; |
343 | |
344 | JsCalledMethod o = null; |
345 | try { |
346 | o = expectUnignoredCall(method, ignorables, methodsCalledList); |
347 | } catch(JsExpectFailedException e) { |
348 | if(!JsExpectFailedException.UNEXPECTED_ON_NONE.equals(e.getReason())) { |
349 | throw e; |
350 | } |
351 | Object[] leftOver = e.getCalledMethods(); |
352 | throw new JsExpectFailedException(e.getMessage(), leftOver, e.getReason()); |
353 | } |
354 | if(o == null) { |
355 | String reason = putTogetherReason(methods, ignorables, methodsCalledList, |
356 | "timed out on next expected method\n"); |
357 | throw new JsExpectFailedException("Timed out waiting for call=" |
358 | +method+"\n"+reason, cleanup(retVal, i), JsExpectFailedException.TIMED_OUT); |
359 | } |
360 | retVal[i] = o; |
361 | if(!method.equals(o.getMethodName()) && !ANY.equals(method)) { |
362 | String reason = putTogetherReason(methods, ignorables, methodsCalledList, null); |
363 | reason += getHowMethodWasCalled(o); |
364 | throw new JsExpectFailedException(reason, cleanup(retVal, i), null); |
365 | } |
366 | } |
367 | |
368 | LeftOverMethods leftOver = getLeftOverMethods(ignorables); |
369 | if(leftOver != null) { |
370 | String reason = putTogetherReason(methods, ignorables, methodsCalledList, "extra method(s)="+leftOver+"\n"); |
371 | reason += getHowMethodWasCalled(leftOver.getMethod(0)); |
372 | JsCalledMethod[] calledOnes = new JsCalledMethod[retVal.length+1]; |
373 | //System.arraycopy(retVal, 0, calledOnes, 0, retVal.length); |
374 | arraycopy(retVal, calledOnes); |
375 | calledOnes[retVal.length] = leftOver.getMethod(0); |
376 | throw new JsExpectFailedException("There was a method called after your expected methods.\n"+reason, calledOnes |
377 | , JsExpectFailedException.UNEXPECTED_CALL_AFTER); |
378 | } |
379 | return retVal; |
380 | } |
381 | private void arraycopy(JsCalledMethod[] retVal, JsCalledMethod[] calledOnes) { |
382 | for(int i = 0; i < retVal.length; i++) { |
383 | calledOnes[i] = retVal[i]; |
384 | } |
385 | } |
386 | private void verifyMethodsExist(String[] methods) { |
387 | for(int i = 0; i < methods.length; i++) { |
388 | verifyMethod(methods[i]); |
389 | } |
390 | } |
391 | private void verifyMethod(String method) { |
392 | //verifyMethod can't be done in GWT |
393 | return; |
394 | // if(MockObject.ANY.equals(method) || MockObject.NONE.equals(method)) |
395 | // return; |
396 | // Class[] classes = getClasses(); |
397 | // if(classes == null) |
398 | // return; |
399 | // |
400 | // String classNames = ""; |
401 | // for(int i = 0; i < classes.length; i++) { |
402 | // //FINEST LOG..... |
403 | // //System.out.println("class="+classes[i].getName()); |
404 | // if(methodExistInThisClass(method, classes[i])) |
405 | // return; |
406 | // classNames += "\n"+classes[i]; |
407 | // } |
408 | // |
409 | // throw new IllegalArgumentException("method='"+method+"' is not a method on any of the" + |
410 | // "\nfollowing Classes/Interfaces"+classNames); |
411 | } |
412 | |
413 | // private boolean methodExistInThisClass(String method, Class c) { |
414 | // return true; |
415 | // //This does not work in GWT testing..... |
416 | // Method[] methods = c.getMethods(); |
417 | // for(int i = 0; i < methods.length; i++) { |
418 | // if(log.isLoggable(Level.FINEST)) |
419 | // log.finest("method in class='"+methods[i].getName()+"' expected='"+method+"'"); |
420 | // if(method.equals(methods[i].getName())) |
421 | // return true; |
422 | // } |
423 | // return false; |
424 | // } |
425 | |
426 | private String putTogetherReason(String[] methods, Set ignorables, List methodsCalled, String lastLine) { |
427 | String reason = "\nMethods you expected...\n"; |
428 | for(int i = 0; i < methods.length; i++) { |
429 | reason += "method["+i+"]="+methods[i]+"\n"; |
430 | } |
431 | reason += "Methods you ignored...\n"; |
432 | //String[] ignored = (String[])ignorables.toArray(new String[0]); |
433 | Object[] ignored = ignorables.toArray(); |
434 | if(ignored.length <= 0) |
435 | reason += "no ignored methods\n"; |
436 | for(int i = 0; i < ignored.length; i++) { |
437 | reason += "ignored["+i+"]="+ignored[i]+"\n"; |
438 | } |
439 | reason += "\nMethods that were called...\n"; |
440 | for(int i = 0; i < methodsCalled.size(); i++) { |
441 | if(ignorables.contains(methodsCalled.get(i))) |
442 | reason += "method["+i+"](ignored)="; |
443 | else |
444 | reason += "method["+i+"]="; |
445 | reason += methodsCalled.get(i)+"\n"; |
446 | } |
447 | if(lastLine == null) |
448 | reason += "(possibly more but we quit after finding unexpected methods)\n"; |
449 | else |
450 | reason += lastLine+"\n"; |
451 | |
452 | |
453 | return reason; |
454 | } |
455 | |
456 | protected synchronized JsCalledMethod expectUnignoredCall(String m, Set ignorables, List calledMethods) { |
457 | |
458 | String method = m; |
459 | if(method == null) |
460 | method = NONE; |
461 | |
462 | //kind of dangerous if used with multiple threads because we might miss |
463 | //a bad event coming in, but if you keep using the same listener for every test |
464 | //the problem should still manifest itself in a |
465 | //different test case which sucks but works. |
466 | if(method.equals(NONE)) { |
467 | System.out.println("method expected="+NONE+" on obj="+this); |
468 | |
469 | // we have to strip out all of the ignored methods from methodsCalled |
470 | //CalledMethod[] methods = (CalledMethod[])methodsCalled.toArray(new CalledMethod[0]); |
471 | Object[] methods = methodsCalled.toArray(); |
472 | for(int i = 0; i < methods.length; i++) |
473 | { |
474 | JsCalledMethod calledMethod = (JsCalledMethod)methods[i]; |
475 | if(ignorables.contains(calledMethod.getMethodName())) |
476 | { |
477 | while(methodsCalled.contains(calledMethod)) |
478 | { |
479 | methodsCalled.remove(calledMethod); |
480 | } |
481 | } |
482 | } |
483 | |
484 | LeftOverMethods leftOver = getLeftOverMethods(ignorables); |
485 | if(leftOver != null) { |
486 | String reason = "You were expecting no methods to be called, but method(s) not\n" |
487 | +"in the ignore list were called earlier. method(s)="+leftOver; |
488 | reason += getHowMethodWasCalled(leftOver.getMethod(0)); |
489 | throw new JsExpectFailedException(reason, leftOver.getMethods(), JsExpectFailedException.UNEXPECTED_ON_NONE); |
490 | } |
491 | return new JsCalledMethod(NONE, null, null); |
492 | } |
493 | |
494 | return waitForUnignoredCall(method, ignorables, calledMethods); |
495 | } |
496 | |
497 | private JsCalledMethod waitForUnignoredCall( |
498 | String logM, Set ignorables, List calledMethods) { |
499 | |
500 | long waitTime2 = waitTime+50; |
501 | // long currentTime; |
502 | //only while waitTime is greater than 50 milliseconds |
503 | while(waitTime2 >= 50) { |
504 | //if there are no methods called yet, since we can't wait like mocklib, throw an exception |
505 | //as all testing will have to happen on test thread!!! |
506 | if(methodsCalled.size() <= 0) { |
507 | return null; |
508 | // currentTime = System.currentTimeMillis(); |
509 | // System.out.println("method expected(not called yet-waiting)="+logM+" on obj="+this+" wait="+waitTime2); |
510 | // this.wait(waitTime2); |
511 | // long waitedOnWait = System.currentTimeMillis() - currentTime; |
512 | // waitTime2 -= waitedOnWait; |
513 | } |
514 | |
515 | //check for new methods to be called now...if no non-ignorable methods, then |
516 | //continue while loop. |
517 | for(int i = 0; i < methodsCalled.size(); i++) { |
518 | JsCalledMethod calledMethod = (JsCalledMethod)methodsCalled.remove(0); |
519 | calledMethods.add(calledMethod); |
520 | if(!ignorables.contains(calledMethod.getMethodName())) { |
521 | System.out.println("method expected and was called="+logM+" on obj="+this); |
522 | return calledMethod; |
523 | } |
524 | } |
525 | } |
526 | |
527 | //return null means timeout.... |
528 | return null; |
529 | } |
530 | |
531 | private Set createIgnorableMap(List ignorableMethods) { |
532 | Set ignorables = new HashSet(); |
533 | if(ignorableMethods != null) { |
534 | for(int i = 0; i < ignorableMethods.size(); i++) |
535 | { |
536 | String method = (String)ignorableMethods.get(i); |
537 | ignorables.add(method); |
538 | } |
539 | } |
540 | return ignorables; |
541 | } |
542 | private LeftOverMethods getLeftOverMethods(Set ignorables) { |
543 | List leftOver = new ArrayList(); |
544 | for(int i = 0; i < methodsCalled.size(); i++) { |
545 | JsCalledMethod o = (JsCalledMethod)methodsCalled.get(i); |
546 | if(o != null && !ignorables.contains(o.getMethodName())) { |
547 | leftOver.add(o); |
548 | } |
549 | } |
550 | if(leftOver.size() <= 0) |
551 | return null; |
552 | |
553 | Object[] m = new Object[0]; |
554 | //m = (CalledMethod[])leftOver.toArray(m); |
555 | m = leftOver.toArray(); |
556 | return new LeftOverMethods(m); |
557 | } |
558 | |
559 | private class LeftOverMethods { |
560 | |
561 | private Object[] leftOver; |
562 | public LeftOverMethods(Object[] m) { |
563 | leftOver = m; |
564 | } |
565 | |
566 | public Object[] getMethods() |
567 | { |
568 | return leftOver; |
569 | } |
570 | |
571 | public int getCalledMethodCount() { |
572 | return leftOver.length; |
573 | } |
574 | public JsCalledMethod getMethod(int index) { |
575 | return (JsCalledMethod)leftOver[index]; |
576 | } |
577 | |
578 | public String toString() { |
579 | String retVal = ""; |
580 | for(int i = 0; i < leftOver.length; i++) { |
581 | retVal+="\n"+leftOver[i]; |
582 | } |
583 | return retVal; |
584 | } |
585 | } |
586 | /** |
587 | * @see biz.xsoftware.mock.JsMockObject#addThrowException(java.lang.String, java.lang.Throwable) |
588 | */ |
589 | public synchronized void addThrowException(String method, Throwable e) { |
590 | if(method == null) |
591 | throw new IllegalArgumentException("method parameter cannot be null"); |
592 | else if(e == null) |
593 | throw new IllegalArgumentException("e parameter to this method cannot be null"); |
594 | List l = (List)methodToReturnVal.get(method); |
595 | if(l == null) { |
596 | l = new ArrayList(); |
597 | methodToReturnVal.put(method, l); |
598 | } |
599 | l.add(e); |
600 | } |
601 | |
602 | /** |
603 | * @see biz.xsoftware.mock.JsMockObject#addReturnValue(java.lang.String, java.lang.Object) |
604 | */ |
605 | public synchronized void addReturnValue(String method, Object o) { |
606 | if(method == null) |
607 | throw new IllegalArgumentException("method parameter cannot be null"); |
608 | List l = (List)methodToReturnVal.get(method); |
609 | if(l == null) { |
610 | l = new ArrayList(); |
611 | methodToReturnVal.put(method, l); |
612 | } |
613 | l.add(o); |
614 | } |
615 | |
616 | public void setDefaultReturnValue(String method, Object o) { |
617 | methodToDefaultRetVal.put(method, o); |
618 | } |
619 | |
620 | /** |
621 | * This is the method that calls the cloner to clone |
622 | * objects like ByteBuffer that can change after |
623 | * they are called. |
624 | * |
625 | * @param o |
626 | */ |
627 | private Object[] clone(String method, Object[] params) { |
628 | if(params == null) |
629 | return null; |
630 | |
631 | //check if the next object is a Behavior object |
632 | List actions = (List)methodToReturnVal.get(method); |
633 | if(actions != null) { |
634 | Object action = actions.get(0); |
635 | if(action instanceof JsBehavior) { |
636 | JsBehavior behavior = (JsBehavior)action; |
637 | return behavior.clone(params); |
638 | } |
639 | } |
640 | |
641 | return params; |
642 | } |
643 | |
644 | public void addBehavior(String method, JsBehavior behavior) { |
645 | if(method == null) |
646 | throw new IllegalArgumentException("method parameter cannot be null"); |
647 | List l = (List)methodToReturnVal.get(method); |
648 | if(l == null) { |
649 | l = new ArrayList(); |
650 | methodToReturnVal.put(method, l); |
651 | } |
652 | l.add(behavior); |
653 | } |
654 | } |