/*
* Copyright 2002-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.beans.factory.config;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import org.junit.Test;
import org.springframework.beans.propertyeditors.StringTrimmerEditor;
import org.springframework.beans.support.ArgumentConvertingMethodInvoker;
import org.springframework.util.MethodInvoker;
import static org.junit.Assert.*;
/**
* Unit tests for {@link MethodInvokingFactoryBean} and {@link MethodInvokingBean}.
*
* @author Colin Sampaleanu
* @author Juergen Hoeller
* @author Chris Beams
* @since 21.11.2003
*/
public class MethodInvokingFactoryBeanTests {
@Test
public void testParameterValidation() throws Exception {
String validationError = "improper validation of input properties";
// assert that only static OR non static are set, but not both or none
MethodInvokingFactoryBean mcfb = new MethodInvokingFactoryBean();
try {
mcfb.afterPropertiesSet();
fail(validationError);
}
catch (IllegalArgumentException ex) {
// expected
}
mcfb = new MethodInvokingFactoryBean();
mcfb.setTargetObject(this);
mcfb.setTargetMethod("whatever");
try {
mcfb.afterPropertiesSet();
fail(validationError);
}
catch (NoSuchMethodException ex) {
// expected
}
// bogus static method
mcfb = new MethodInvokingFactoryBean();
mcfb.setTargetClass(TestClass1.class);
mcfb.setTargetMethod("some.bogus.Method.name");
try {
mcfb.afterPropertiesSet();
fail(validationError);
}
catch (NoSuchMethodException ex) {
// expected
}
// bogus static method
mcfb = new MethodInvokingFactoryBean();
mcfb.setTargetClass(TestClass1.class);
mcfb.setTargetMethod("method1");
try {
mcfb.afterPropertiesSet();
fail(validationError);
}
catch (IllegalArgumentException ex) {
// expected
}
// missing method
mcfb = new MethodInvokingFactoryBean();
mcfb.setTargetObject(this);
try {
mcfb.afterPropertiesSet();
fail(validationError);
}
catch (IllegalArgumentException ex) {
// expected
}
// bogus method
mcfb = new MethodInvokingFactoryBean();
mcfb.setTargetObject(this);
mcfb.setTargetMethod("bogus");
try {
mcfb.afterPropertiesSet();
fail(validationError);
}
catch (NoSuchMethodException ex) {
// expected
}
// static method
TestClass1._staticField1 = 0;
mcfb = new MethodInvokingFactoryBean();
mcfb.setTargetClass(TestClass1.class);
mcfb.setTargetMethod("staticMethod1");
mcfb.afterPropertiesSet();
// non-static method
TestClass1 tc1 = new TestClass1();
mcfb = new MethodInvokingFactoryBean();
mcfb.setTargetObject(tc1);
mcfb.setTargetMethod("method1");
mcfb.afterPropertiesSet();
}
@Test
public void testGetObjectType() throws Exception {
TestClass1 tc1 = new TestClass1();
MethodInvokingFactoryBean mcfb = new MethodInvokingFactoryBean();
mcfb = new MethodInvokingFactoryBean();
mcfb.setTargetObject(tc1);
mcfb.setTargetMethod("method1");
mcfb.afterPropertiesSet();
assertTrue(int.class.equals(mcfb.getObjectType()));
mcfb = new MethodInvokingFactoryBean();
mcfb.setTargetClass(TestClass1.class);
mcfb.setTargetMethod("voidRetvalMethod");
mcfb.afterPropertiesSet();
Class<?> objType = mcfb.getObjectType();
assertTrue(objType.equals(void.class));
// verify that we can call a method with args that are subtypes of the
// target method arg types
TestClass1._staticField1 = 0;
mcfb = new MethodInvokingFactoryBean();
mcfb.setTargetClass(TestClass1.class);
mcfb.setTargetMethod("supertypes");
mcfb.setArguments(new Object[] {new ArrayList<>(), new ArrayList<Object>(), "hello"});
mcfb.afterPropertiesSet();
mcfb.getObjectType();
// fail on improper argument types at afterPropertiesSet
mcfb = new MethodInvokingFactoryBean();
mcfb.registerCustomEditor(String.class, new StringTrimmerEditor(false));
mcfb.setTargetClass(TestClass1.class);
mcfb.setTargetMethod("supertypes");
mcfb.setArguments(new Object[] {"1", new Object()});
try {
mcfb.afterPropertiesSet();
fail("Should have thrown NoSuchMethodException");
}
catch (NoSuchMethodException ex) {
// expected
}
}
@Test
public void testGetObject() throws Exception {
// singleton, non-static
TestClass1 tc1 = new TestClass1();
MethodInvokingFactoryBean mcfb = new MethodInvokingFactoryBean();
mcfb.setTargetObject(tc1);
mcfb.setTargetMethod("method1");
mcfb.afterPropertiesSet();
Integer i = (Integer) mcfb.getObject();
assertEquals(1, i.intValue());
i = (Integer) mcfb.getObject();
assertEquals(1, i.intValue());
// non-singleton, non-static
tc1 = new TestClass1();
mcfb = new MethodInvokingFactoryBean();
mcfb.setTargetObject(tc1);
mcfb.setTargetMethod("method1");
mcfb.setSingleton(false);
mcfb.afterPropertiesSet();
i = (Integer) mcfb.getObject();
assertEquals(1, i.intValue());
i = (Integer) mcfb.getObject();
assertEquals(2, i.intValue());
// singleton, static
TestClass1._staticField1 = 0;
mcfb = new MethodInvokingFactoryBean();
mcfb.setTargetClass(TestClass1.class);
mcfb.setTargetMethod("staticMethod1");
mcfb.afterPropertiesSet();
i = (Integer) mcfb.getObject();
assertEquals(1, i.intValue());
i = (Integer) mcfb.getObject();
assertEquals(1, i.intValue());
// non-singleton, static
TestClass1._staticField1 = 0;
mcfb = new MethodInvokingFactoryBean();
mcfb.setStaticMethod("org.springframework.beans.factory.config.MethodInvokingFactoryBeanTests$TestClass1.staticMethod1");
mcfb.setSingleton(false);
mcfb.afterPropertiesSet();
i = (Integer) mcfb.getObject();
assertEquals(1, i.intValue());
i = (Integer) mcfb.getObject();
assertEquals(2, i.intValue());
// void return value
mcfb = new MethodInvokingFactoryBean();
mcfb.setTargetClass(TestClass1.class);
mcfb.setTargetMethod("voidRetvalMethod");
mcfb.afterPropertiesSet();
assertNull(mcfb.getObject());
// now see if we can match methods with arguments that have supertype arguments
mcfb = new MethodInvokingFactoryBean();
mcfb.setTargetClass(TestClass1.class);
mcfb.setTargetMethod("supertypes");
mcfb.setArguments(new Object[] {new ArrayList<>(), new ArrayList<Object>(), "hello"});
// should pass
mcfb.afterPropertiesSet();
}
@Test
public void testArgumentConversion() throws Exception {
MethodInvokingFactoryBean mcfb = new MethodInvokingFactoryBean();
mcfb.setTargetClass(TestClass1.class);
mcfb.setTargetMethod("supertypes");
mcfb.setArguments(new Object[] {new ArrayList<>(), new ArrayList<Object>(), "hello", "bogus"});
try {
mcfb.afterPropertiesSet();
fail("Matched method with wrong number of args");
}
catch (NoSuchMethodException ex) {
// expected
}
mcfb = new MethodInvokingFactoryBean();
mcfb.setTargetClass(TestClass1.class);
mcfb.setTargetMethod("supertypes");
mcfb.setArguments(new Object[] {1, new Object()});
try {
mcfb.afterPropertiesSet();
mcfb.getObject();
fail("Should have failed on getObject with mismatched argument types");
}
catch (NoSuchMethodException ex) {
// expected
}
mcfb = new MethodInvokingFactoryBean();
mcfb.setTargetClass(TestClass1.class);
mcfb.setTargetMethod("supertypes2");
mcfb.setArguments(new Object[] {new ArrayList<>(), new ArrayList<Object>(), "hello", "bogus"});
mcfb.afterPropertiesSet();
assertEquals("hello", mcfb.getObject());
mcfb = new MethodInvokingFactoryBean();
mcfb.setTargetClass(TestClass1.class);
mcfb.setTargetMethod("supertypes2");
mcfb.setArguments(new Object[] {new ArrayList<>(), new ArrayList<Object>(), new Object()});
try {
mcfb.afterPropertiesSet();
fail("Matched method when shouldn't have matched");
}
catch (NoSuchMethodException ex) {
// expected
}
}
@Test
public void testInvokeWithNullArgument() throws Exception {
MethodInvoker methodInvoker = new MethodInvoker();
methodInvoker.setTargetClass(TestClass1.class);
methodInvoker.setTargetMethod("nullArgument");
methodInvoker.setArguments(new Object[] {null});
methodInvoker.prepare();
methodInvoker.invoke();
}
@Test
public void testInvokeWithIntArgument() throws Exception {
ArgumentConvertingMethodInvoker methodInvoker = new ArgumentConvertingMethodInvoker();
methodInvoker.setTargetClass(TestClass1.class);
methodInvoker.setTargetMethod("intArgument");
methodInvoker.setArguments(new Object[] {5});
methodInvoker.prepare();
methodInvoker.invoke();
methodInvoker = new ArgumentConvertingMethodInvoker();
methodInvoker.setTargetClass(TestClass1.class);
methodInvoker.setTargetMethod("intArgument");
methodInvoker.setArguments(new Object[] {"5"});
methodInvoker.prepare();
methodInvoker.invoke();
}
@Test
public void testInvokeWithIntArguments() throws Exception {
MethodInvokingBean methodInvoker = new MethodInvokingBean();
methodInvoker.setTargetClass(TestClass1.class);
methodInvoker.setTargetMethod("intArguments");
methodInvoker.setArguments(new Object[]{new Integer[] {5, 10}});
methodInvoker.afterPropertiesSet();
methodInvoker = new MethodInvokingBean();
methodInvoker.setTargetClass(TestClass1.class);
methodInvoker.setTargetMethod("intArguments");
methodInvoker.setArguments(new Object[]{new String[]{"5", "10"}});
methodInvoker.afterPropertiesSet();
methodInvoker = new MethodInvokingBean();
methodInvoker.setTargetClass(TestClass1.class);
methodInvoker.setTargetMethod("intArguments");
methodInvoker.setArguments(new Object[]{new Integer[] {5, 10}});
methodInvoker.afterPropertiesSet();
methodInvoker = new MethodInvokingBean();
methodInvoker.setTargetClass(TestClass1.class);
methodInvoker.setTargetMethod("intArguments");
methodInvoker.setArguments(new String[]{"5", "10"});
methodInvoker.afterPropertiesSet();
methodInvoker = new MethodInvokingBean();
methodInvoker.setTargetClass(TestClass1.class);
methodInvoker.setTargetMethod("intArguments");
methodInvoker.setArguments(new Object[]{new Integer[] {5, 10}});
methodInvoker.afterPropertiesSet();
methodInvoker = new MethodInvokingBean();
methodInvoker.setTargetClass(TestClass1.class);
methodInvoker.setTargetMethod("intArguments");
methodInvoker.setArguments(new Object[]{"5", "10"});
methodInvoker.afterPropertiesSet();
}
public static class TestClass1 {
public static int _staticField1;
public int _field1 = 0;
public int method1() {
return ++_field1;
}
public static int staticMethod1() {
return ++TestClass1._staticField1;
}
public static void voidRetvalMethod() {
}
public static void nullArgument(Object arg) {
}
public static void intArgument(int arg) {
}
public static void intArguments(int[] arg) {
}
public static String supertypes(Collection<?> c, Integer i) {
return i.toString();
}
public static String supertypes(Collection<?> c, List<?> l, String s) {
return s;
}
public static String supertypes2(Collection<?> c, List<?> l, Integer i) {
return i.toString();
}
public static String supertypes2(Collection<?> c, List<?> l, String s, Integer i) {
return s;
}
public static String supertypes2(Collection<?> c, List<?> l, String s, String s2) {
return s;
}
}
}