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: */
017:
018: package org.apache.commons.beanutils;
019:
020: import java.io.OutputStream;
021: import java.io.PrintStream;
022:
023: import java.lang.reflect.Method;
024: import java.lang.reflect.Modifier;
025:
026: import org.apache.commons.beanutils.priv.PrivateBeanFactory;
027: import org.apache.commons.beanutils.priv.PublicSubBean;
028:
029: import junit.framework.TestCase;
030: import junit.framework.Test;
031: import junit.framework.TestSuite;
032:
033: /**
034: * <p> Test case for <code>MethodUtils</code> </p>
035: *
036: */
037: public class MethodUtilsTestCase extends TestCase {
038:
039: // ---------------------------------------------------------- Constructors
040:
041: /**
042: * Construct a new instance of this test case.
043: *
044: * @param name Name of the test case
045: */
046: public MethodUtilsTestCase(String name) {
047: super (name);
048: }
049:
050: // -------------------------------------------------- Overall Test Methods
051:
052: /**
053: * Set up instance variables required by this test case.
054: */
055: public void setUp() {
056: }
057:
058: /**
059: * Return the tests included in this test suite.
060: */
061: public static Test suite() {
062: return (new TestSuite(MethodUtilsTestCase.class));
063: }
064:
065: /**
066: * Tear down instance variables required by this test case.
067: */
068: public void tearDown() {
069: }
070:
071: // ------------------------------------------------ Individual Test Methods
072:
073: /**
074: * <p> Test <code>getAccessibleMethod</code>.
075: */
076: public void testGetAccessibleMethod() {
077: // test MethodUtils.getAccessibleMethod
078: // we'll make things easier by using the convenience methods
079:
080: // easy bit first - find a public method
081: // METHOD ONE
082: Method method = MethodUtils.getAccessibleMethod(TestBean.class,
083: "setStringProperty", String.class);
084:
085: // check that we've found one that matches
086: assertNotNull(method);
087: assertEquals("method ONE is named correctly",
088: "setStringProperty", method.getName());
089: assertTrue("Method ONE is public", Modifier.isPublic(method
090: .getModifiers()));
091:
092: // trickier this one - find a method in a direct interface
093: // METHOD TWO
094: method = MethodUtils.getAccessibleMethod(PrivateBeanFactory
095: .create().getClass(), "methodBar", String.class);
096:
097: // check that we've found one that matches
098: assertNotNull(method);
099: assertEquals("Method TWO is named correctly", "methodBar",
100: method.getName());
101: assertTrue("Method TWO is public", Modifier.isPublic(method
102: .getModifiers()));
103:
104: // trickier this one - find a method in a indirect interface
105: // METHOD THREE
106: method = MethodUtils
107: .getAccessibleMethod(PrivateBeanFactory
108: .createSubclass().getClass(), "methodBaz",
109: String.class);
110:
111: // check that we've found one that matches
112: assertNotNull(method);
113: assertEquals("Method THREE is named correctly", "methodBaz",
114: method.getName());
115: assertTrue("Method THREE is public", Modifier.isPublic(method
116: .getModifiers()));
117:
118: }
119:
120: /**
121: * <p> Test <code>invokeExactMethod</code>.
122: */
123: public void testInvokeExactMethod() {
124: // test MethodUtils.invokeExactMethod
125: // easy bit first - invoke a public method
126: // METHOD ONE
127: try {
128:
129: TestBean bean = new TestBean();
130: Object ret = MethodUtils.invokeExactMethod(bean,
131: "setStringProperty", "TEST");
132: // check that the return's right and that the properties been set
133: assertNull(ret);
134: assertEquals("Method ONE was invoked", "TEST", bean
135: .getStringProperty());
136:
137: } catch (Throwable t) {
138: // ONE
139: fail("Exception in method ONE prevented invokation: "
140: + t.toString());
141: }
142:
143: // trickier this one - find a method in a direct interface
144: // METHOD TWO FAILURE
145: try {
146:
147: Object ret = MethodUtils.invokeExactMethod(
148: PrivateBeanFactory.create(), "methodBar",
149: "ANOTHER TEST");
150:
151: // check that we've found one that matches
152: assertEquals("Method TWO was invoked correctly",
153: "ANOTHER TEST", ret);
154:
155: } catch (Throwable t) {
156: // METHOD TWO FAILURE
157: fail("Exception in method TWO prevented invokation: "
158: + t.toString());
159: }
160:
161: // trickier this one - find a method in a indirect interface
162: // METHOD THREE
163: try {
164:
165: Object ret = MethodUtils.invokeExactMethod(
166: PrivateBeanFactory.createSubclass(), "methodBaz",
167: "YET ANOTHER TEST");
168:
169: // check that we've found one that matches
170: assertEquals("Method TWO was invoked correctly",
171: "YET ANOTHER TEST", ret);
172:
173: } catch (Throwable t) {
174: // METHOD THREE FAILURE
175: fail("Exception in method THREE prevented invokation: "
176: + t.toString());
177:
178: }
179: }
180:
181: /**
182: * <p> Test <code>invokeMethod</code>.
183: */
184: public void testInvokeMethod() throws Exception {
185: // i'm going to test that the actual calls work first and then try them via reflection
186:
187: AbstractParent parent = new AlphaBean("parent");
188:
189: // try testAddChild through abstract superclass
190: BetaBean childOne = new BetaBean("ChildOne");
191:
192: assertEquals("Oh no! Badly coded test case! (1)", "ChildOne",
193: parent.testAddChild(childOne));
194:
195: // let's try MethodUtils version
196: assertEquals("Cannot invoke through abstract class (1)",
197: "ChildOne", MethodUtils.invokeMethod(parent,
198: "testAddChild", childOne));
199:
200: // try adding through interface
201: AlphaBean childTwo = new AlphaBean("ChildTwo");
202:
203: assertEquals("Oh no! Badly coded test case! (2)", "ChildTwo",
204: parent.testAddChild(childTwo));
205:
206: // let's try MethodUtils version
207: assertEquals("Cannot invoke through interface (1)", "ChildTwo",
208: MethodUtils.invokeMethod(parent, "testAddChild",
209: childTwo));
210:
211: Object[] params = new Object[2];
212:
213: assertEquals("Oh no! Badly coded test case! (3)", "ChildOne",
214: parent.testAddChild2("parameter", childOne));
215:
216: // let's try MethodUtils version
217: params[0] = "parameter";
218: params[1] = childOne;
219:
220: assertEquals("Cannot invoke through abstract class (1)",
221: "ChildOne", MethodUtils.invokeMethod(parent,
222: "testAddChild2", params));
223:
224: assertEquals("Oh no! Badly coded test case! (4)", "ChildTwo",
225: parent.testAddChild2("parameter", childTwo));
226:
227: // let's try MethodUtils version
228: params[0] = "parameter";
229: params[1] = childTwo;
230:
231: assertEquals("Cannot invoke through abstract class (1)",
232: "ChildTwo", MethodUtils.invokeMethod(parent,
233: "testAddChild2", params));
234:
235: // test that exception is correctly thrown when a method cannot be found with matching params
236: try {
237: // the next line
238: parent = new AlphaBean("parent");
239: childOne = new BetaBean("ChildOne");
240: MethodUtils.invokeMethod(parent, "bogus", childOne);
241: // should get here!
242: fail("No exception thrown when no appropriate method exists");
243:
244: } catch (NoSuchMethodException e) {
245: // this is what we're expecting!
246: }
247:
248: MethodUtils.invokeMethod(parent, "getName", null);
249: MethodUtils.invokeMethod(parent, "getName", null, null);
250: MethodUtils.invokeExactMethod(parent, "getName", null);
251: MethodUtils.invokeExactMethod(parent, "getName", null, null);
252: }
253:
254: /**
255: * <p> Test <code>invokeMethod</code> with a primitive.
256: */
257: public void testInvokeMethodWithPrimitives() throws Exception {
258: // first test that the bean works
259: PrimitiveBean bean = new PrimitiveBean();
260: bean.setFloat(20.0f);
261: bean.setLong(10l);
262: bean.setBoolean(true);
263: bean.setInt(12);
264: bean.setDouble(25.5d);
265:
266: assertEquals("Bug in PrimitiveBean (1)", 20.0f,
267: bean.getFloat(), 0.01f);
268: assertEquals("Bug in PrimitiveBean (2)", 10, bean.getLong());
269: assertEquals("Bug in PrimitiveBean (3)", true, bean
270: .getBoolean());
271: assertEquals("Bug in PrimitiveBean (4)", 12, bean.getInt());
272: assertEquals("Bug in PrimitiveBean (5)", 25.5d, bean
273: .getDouble(), 0.01f);
274:
275: bean = new PrimitiveBean();
276: MethodUtils.invokeMethod(bean, "setBoolean", new Boolean(true));
277: assertEquals("Call boolean property using invokeMethod", true,
278: bean.getBoolean());
279:
280: bean = new PrimitiveBean();
281: MethodUtils.invokeMethod(bean, "setFloat", new Float(20.0f));
282: assertEquals("Call float property using invokeMethod", 20.0f,
283: bean.getFloat(), 0.01f);
284:
285: bean = new PrimitiveBean();
286: MethodUtils.invokeMethod(bean, "setLong", new Long(10));
287: assertEquals("Call float property using invokeMethod", 10, bean
288: .getLong());
289:
290: bean = new PrimitiveBean();
291: MethodUtils.invokeMethod(bean, "setInt", new Integer(12));
292: assertEquals("Set float property using invokeMethod", 12, bean
293: .getInt());
294:
295: bean = new PrimitiveBean();
296: MethodUtils.invokeMethod(bean, "setDouble", new Double(25.5d));
297: assertEquals("Set float property using invokeMethod", 25.5d,
298: bean.getDouble(), 0.01d);
299: }
300:
301: public void testStaticInvokeMethod() throws Exception {
302:
303: Object value = null;
304: int current = TestBean.currentCounter();
305:
306: value = MethodUtils.invokeStaticMethod(TestBean.class,
307: "currentCounter", new Object[0]);
308: assertEquals("currentCounter value", current, ((Integer) value)
309: .intValue());
310:
311: MethodUtils.invokeStaticMethod(TestBean.class,
312: "incrementCounter", new Object[0]);
313: current++;
314:
315: value = MethodUtils.invokeStaticMethod(TestBean.class,
316: "currentCounter", new Object[0]);
317: assertEquals("currentCounter value", current, ((Integer) value)
318: .intValue());
319:
320: MethodUtils.invokeStaticMethod(TestBean.class,
321: "incrementCounter", new Object[] { new Integer(8) });
322: current += 8;
323:
324: value = MethodUtils.invokeStaticMethod(TestBean.class,
325: "currentCounter", new Object[0]);
326: assertEquals("currentCounter value", current, ((Integer) value)
327: .intValue());
328:
329: MethodUtils.invokeExactStaticMethod(TestBean.class,
330: "incrementCounter", new Object[] { new Integer(8) },
331: new Class[] { Number.class });
332: current += 16;
333:
334: value = MethodUtils.invokeStaticMethod(TestBean.class,
335: "currentCounter", new Object[0]);
336: assertEquals("currentCounter value", current, ((Integer) value)
337: .intValue());
338: }
339:
340: /**
341: * Simple tests for accessing static methods via invokeMethod().
342: */
343: public void testSimpleStatic1() {
344:
345: TestBean bean = new TestBean();
346: Object value = null;
347: int current = TestBean.currentCounter();
348:
349: try {
350:
351: // Return initial value of the counter
352: value = MethodUtils.invokeMethod(bean, "currentCounter",
353: new Object[0], new Class[0]);
354: assertNotNull("currentCounter exists", value);
355: assertTrue("currentCounter type", value instanceof Integer);
356: assertEquals("currentCounter value", current,
357: ((Integer) value).intValue());
358:
359: // Increment via no-arguments version
360: MethodUtils.invokeMethod(bean, "incrementCounter",
361: new Object[0], new Class[0]);
362:
363: // Validate updated value
364: current++;
365: value = MethodUtils.invokeMethod(bean, "currentCounter",
366: new Object[0], new Class[0]);
367: assertNotNull("currentCounter exists", value);
368: assertTrue("currentCounter type", value instanceof Integer);
369: assertEquals("currentCounter value", current,
370: ((Integer) value).intValue());
371:
372: // Increment via specified-argument version
373: MethodUtils.invokeMethod(bean, "incrementCounter",
374: new Object[] { new Integer(5) },
375: new Class[] { Integer.TYPE });
376:
377: // Validate updated value
378: current += 5;
379: value = MethodUtils.invokeMethod(bean, "currentCounter",
380: new Object[0], new Class[0]);
381: assertNotNull("currentCounter exists", value);
382: assertTrue("currentCounter type", value instanceof Integer);
383: assertEquals("currentCounter value", current,
384: ((Integer) value).intValue());
385:
386: } catch (Exception e) {
387: fail("Threw exception" + e);
388: }
389:
390: }
391:
392: /**
393: * Simple tests for accessing static methods via invokeExactMethod().
394: */
395: public void testSimpleStatic2() {
396:
397: TestBean bean = new TestBean();
398: Object value = null;
399: int current = TestBean.currentCounter();
400:
401: try {
402:
403: // Return initial value of the counter
404: value = MethodUtils.invokeExactMethod(bean,
405: "currentCounter", new Object[0], new Class[0]);
406: assertNotNull("currentCounter exists", value);
407: assertTrue("currentCounter type", value instanceof Integer);
408: assertEquals("currentCounter value", current,
409: ((Integer) value).intValue());
410:
411: // Increment via no-arguments version
412: MethodUtils.invokeExactMethod(bean, "incrementCounter",
413: new Object[0], new Class[0]);
414:
415: // Validate updated value
416: current++;
417: value = MethodUtils.invokeExactMethod(bean,
418: "currentCounter", new Object[0], new Class[0]);
419: assertNotNull("currentCounter exists", value);
420: assertTrue("currentCounter type", value instanceof Integer);
421: assertEquals("currentCounter value", current,
422: ((Integer) value).intValue());
423:
424: // Increment via specified-argument version
425: MethodUtils.invokeExactMethod(bean, "incrementCounter",
426: new Object[] { new Integer(5) },
427: new Class[] { Integer.TYPE });
428:
429: // Validate updated value
430: current += 5;
431: value = MethodUtils.invokeExactMethod(bean,
432: "currentCounter", new Object[0], new Class[0]);
433: assertNotNull("currentCounter exists", value);
434: assertTrue("currentCounter type", value instanceof Integer);
435: assertEquals("currentCounter value", current,
436: ((Integer) value).intValue());
437:
438: } catch (Exception e) {
439: fail("Threw exception" + e);
440: }
441:
442: }
443:
444: /**
445: * Simple tests for accessing static methods via getAccessibleMethod()
446: */
447: public void testSimpleStatic3() {
448:
449: Object value = null;
450: int current = TestBean.currentCounter();
451:
452: try {
453:
454: // Acquire the methods we need
455: Method currentCounterMethod = MethodUtils
456: .getAccessibleMethod(TestBean.class,
457: "currentCounter", new Class[0]);
458: assertNotNull("currentCounterMethod exists",
459: currentCounterMethod);
460: assertEquals("currentCounterMethod name", "currentCounter",
461: currentCounterMethod.getName());
462: assertEquals("currentCounterMethod args", 0,
463: currentCounterMethod.getParameterTypes().length);
464: assertTrue("currentCounterMethod public", Modifier
465: .isPublic(currentCounterMethod.getModifiers()));
466: assertTrue("currentCounterMethod static", Modifier
467: .isStatic(currentCounterMethod.getModifiers()));
468: Method incrementCounterMethod1 = MethodUtils
469: .getAccessibleMethod(TestBean.class,
470: "incrementCounter", new Class[0]);
471: assertNotNull("incrementCounterMethod1 exists",
472: incrementCounterMethod1);
473: assertEquals("incrementCounterMethod1 name",
474: "incrementCounter", incrementCounterMethod1
475: .getName());
476: assertEquals("incrementCounterMethod1 args", 0,
477: incrementCounterMethod1.getParameterTypes().length);
478: assertTrue("incrementCounterMethod1 public", Modifier
479: .isPublic(incrementCounterMethod1.getModifiers()));
480: assertTrue("incrementCounterMethod1 static", Modifier
481: .isStatic(incrementCounterMethod1.getModifiers()));
482: Method incrementCounterMethod2 = MethodUtils
483: .getAccessibleMethod(TestBean.class,
484: "incrementCounter",
485: new Class[] { Integer.TYPE });
486: assertNotNull("incrementCounterMethod2 exists",
487: incrementCounterMethod2);
488: assertEquals("incrementCounterMethod2 name",
489: "incrementCounter", incrementCounterMethod2
490: .getName());
491: assertEquals("incrementCounterMethod2 args", 1,
492: incrementCounterMethod2.getParameterTypes().length);
493: assertTrue("incrementCounterMethod2 public", Modifier
494: .isPublic(incrementCounterMethod2.getModifiers()));
495: assertTrue("incrementCounterMethod2 static", Modifier
496: .isStatic(incrementCounterMethod2.getModifiers()));
497:
498: // Return initial value of the counter
499: value = currentCounterMethod.invoke(null, new Object[0]);
500: assertNotNull("currentCounter exists", value);
501: assertTrue("currentCounter type", value instanceof Integer);
502: assertEquals("currentCounter value", current,
503: ((Integer) value).intValue());
504:
505: // Increment via no-arguments version
506: incrementCounterMethod1.invoke(null, new Object[0]);
507:
508: // Validate updated value
509: current++;
510: value = currentCounterMethod.invoke(null, new Object[0]);
511: assertNotNull("currentCounter exists", value);
512: assertTrue("currentCounter type", value instanceof Integer);
513: assertEquals("currentCounter value", current,
514: ((Integer) value).intValue());
515:
516: // Increment via specified-argument version
517: incrementCounterMethod2.invoke(null,
518: new Object[] { new Integer(5) });
519:
520: // Validate updated value
521: current += 5;
522: value = currentCounterMethod.invoke(null, new Object[0]);
523: assertNotNull("currentCounter exists", value);
524: assertTrue("currentCounter type", value instanceof Integer);
525: assertEquals("currentCounter value", current,
526: ((Integer) value).intValue());
527:
528: } catch (Exception e) {
529: fail("Threw exception" + e);
530: }
531:
532: }
533:
534: public void testPublicSub() throws Exception {
535: // make sure that bean does what it should
536: PublicSubBean bean = new PublicSubBean();
537: assertEquals("Start value (foo)", bean.getFoo(), "This is foo");
538: assertEquals("Start value (bar)", bean.getBar(), "This is bar");
539: bean.setFoo("new foo");
540: bean.setBar("new bar");
541: assertEquals("Set value (foo)", bean.getFoo(), "new foo");
542: assertEquals("Set value (bar)", bean.getBar(), "new bar");
543:
544: // see if we can access public methods in a default access superclass
545: // from a public access subclass instance
546: MethodUtils.invokeMethod(bean, "setFoo", "alpha");
547: assertEquals("Set value (foo:2)", bean.getFoo(), "alpha");
548: MethodUtils.invokeMethod(bean, "setBar", "beta");
549: assertEquals("Set value (bar:2)", bean.getFoo(), "alpha");
550: }
551:
552: public void testParentMethod() throws Exception {
553: OutputStream os = new PrintStream(System.out);
554: PrintStream ps = new PrintStream(System.out);
555:
556: A a = new A();
557: MethodUtils.invokeMethod(a, "foo", os);
558: assertTrue("Method Invoked(1)", a.called);
559:
560: a = new A();
561: MethodUtils.invokeMethod(a, "foo", ps);
562: assertTrue("Method Invoked(2)", a.called);
563: }
564: }
|