/*******************************************************************************
* Copyright (c) 2005, 2014 springside.github.io
*
* Licensed under the Apache License, Version 2.0 (the "License");
*******************************************************************************/
package org.springside.modules.utils.reflect;
import static org.assertj.core.api.Assertions.*;
import java.lang.reflect.InvocationTargetException;
import org.junit.Test;
import org.springside.modules.utils.base.ExceptionUtil.UncheckedException;
public class ReflectionUtilTest {
@Test
public void getAndSetFieldValue() {
TestBean bean = new TestBean();
// 无需getter函数, 直接读取privateField
assertThat(ReflectionUtil.getFieldValue(bean, "privateField")).isEqualTo(1);
// 先尝试getter函数, 然后直接读取privateField
assertThat(ReflectionUtil.getProperty(bean, "privateField")).isEqualTo(1);
// 绕过将publicField+1的getter函数,直接读取publicField的原始值
assertThat(ReflectionUtil.getFieldValue(bean, "publicField")).isEqualTo(1);
// 先尝试getter函数, 成功则补不直接读取publicField
assertThat(ReflectionUtil.getProperty(bean, "publicField")).isEqualTo(2);
bean = new TestBean();
// 无需setter函数, 直接设置privateField
ReflectionUtil.setFieldValue(bean, "privateField", 2);
assertThat(bean.inspectPrivateField()).isEqualTo(2);
ReflectionUtil.setProperty(bean, "privateField", 3);
assertThat(bean.inspectPrivateField()).isEqualTo(3);
// 绕过将publicField+1的setter函数,直接设置publicField的原始值
ReflectionUtil.setFieldValue(bean, "publicField", 2);
assertThat(bean.inspectPublicField()).isEqualTo(2);
// 没有绕过将publicField+1的setter函数
ReflectionUtil.setProperty(bean, "publicField", 3);
assertThat(bean.inspectPublicField()).isEqualTo(4);
try {
ReflectionUtil.getFieldValue(bean, "notExist");
failBecauseExceptionWasNotThrown(IllegalArgumentException.class);
} catch (IllegalArgumentException e) {
}
try {
ReflectionUtil.setFieldValue(bean, "notExist", 2);
failBecauseExceptionWasNotThrown(IllegalArgumentException.class);
} catch (IllegalArgumentException e) {
}
}
@Test
public void invokeGetterAndSetter() {
TestBean bean = new TestBean();
assertThat(ReflectionUtil.invokeGetter(bean, "publicField")).isEqualTo(bean.inspectPublicField() + 1);
MethodInvoker invoker = MethodInvoker.createGetter(TestBean.class, "publicField");
assertThat(invoker.invoke(bean)).isEqualTo(bean.inspectPublicField() + 1);
bean = new TestBean();
// 通过setter的函数将+1
ReflectionUtil.invokeSetter(bean, "publicField", 10);
assertThat(bean.inspectPublicField()).isEqualTo(10 + 1);
MethodInvoker invoker2 = MethodInvoker.createSetter(TestBean.class, "publicField", Integer.class);
invoker2.invoke(bean, 12);
assertThat(bean.inspectPublicField()).isEqualTo(12 + 1);
}
@Test
public void invokeMethod() {
TestBean bean = new TestBean();
// 使用函数名+参数类型的匹配, 支持传参数
assertThat(ReflectionUtil.invokeMethod(bean, "privateMethod", new Object[] { "calvin" }))
.isEqualTo("hello calvin");
// 使用函数名+参数类型的匹配
assertThat(ReflectionUtil.invokeMethod(bean, "privateMethod", new Object[] { "calvin" },
new Class[] { String.class })).isEqualTo("hello calvin");
// MethodInvoker
MethodInvoker invoker = MethodInvoker.createMethod(bean.getClass(), "privateMethod", String.class);
assertThat(invoker.invoke(bean, new Object[] { "calvin" })).isEqualTo("hello calvin");
// 仅匹配函数名
assertThat(ReflectionUtil.invokeMethodByName(bean, "privateMethod", new Object[] { "calvin" }))
.isEqualTo("hello calvin");
// 函数名错
try {
ReflectionUtil.invokeMethod(bean, "notExistMethod", new Object[] { "calvin" },
new Class[] { String.class });
failBecauseExceptionWasNotThrown(IllegalArgumentException.class);
} catch (IllegalArgumentException e) {
}
// 函数名错
try {
MethodInvoker.createMethod(bean.getClass(), "notExistMethod", String.class);
failBecauseExceptionWasNotThrown(IllegalArgumentException.class);
} catch (IllegalArgumentException e) {
}
// 参数类型错
try {
ReflectionUtil.invokeMethod(bean, "privateMethod", new Object[] { "calvin" },
new Class[] { Integer.class });
failBecauseExceptionWasNotThrown(RuntimeException.class);
} catch (RuntimeException e) {
}
// 参数类型错
try {
MethodInvoker.createMethod(bean.getClass(), "privateMethod", Integer.class);
failBecauseExceptionWasNotThrown(IllegalArgumentException.class);
} catch (IllegalArgumentException e) {
}
// 函数名错
try {
ReflectionUtil.invokeMethodByName(bean, "notExistMethod", new Object[] { "calvin" });
failBecauseExceptionWasNotThrown(IllegalArgumentException.class);
} catch (IllegalArgumentException e) {
}
}
@Test
public void invokeConstructor() {
TestBean bean = ReflectionUtil.invokeConstructor(TestBean.class);
assertThat(bean.getPublicField()).isEqualTo(2);
TestBean3 bean3 = ReflectionUtil.invokeConstructor(TestBean3.class, 4);
assertThat(bean3.getId()).isEqualTo(4);
}
@Test
public void convertReflectionExceptionToUnchecked() {
IllegalArgumentException iae = new IllegalArgumentException();
// ReflectionException,normal
RuntimeException e = ReflectionUtil.convertReflectionExceptionToUnchecked(iae);
assertThat(e).isEqualTo(iae);
// InvocationTargetException,extract it's target exception.
Exception ex = new Exception();
e = ReflectionUtil.convertReflectionExceptionToUnchecked(new InvocationTargetException(ex));
assertThat(e.getCause()).isEqualTo(ex);
// UncheckedException, ignore it.
RuntimeException re = new RuntimeException("abc");
e = ReflectionUtil.convertReflectionExceptionToUnchecked(re);
assertThat(e).hasMessage("abc");
// Unexcepted Checked exception.
e = ReflectionUtil.convertReflectionExceptionToUnchecked(ex);
assertThat(e).isInstanceOf(UncheckedException.class);
}
public static class ParentBean<T, ID> {
}
public static class TestBean extends ParentBean<String, Long> {
/** 没有getter/setter的field */
private int privateField = 1;
/** 有getter/setter的field */
private int publicField = 1;
// 通過getter函數會比屬性值+1
public int getPublicField() {
return publicField + 1;
}
// 通過setter函數會被比輸入值加1
public void setPublicField(int publicField) {
this.publicField = publicField + 1;
}
public int inspectPrivateField() {
return privateField;
}
public int inspectPublicField() {
return publicField;
}
private String privateMethod(String text) {
return "hello " + text;
}
}
public static class TestBean2 extends ParentBean {
}
public static class TestBean3 {
public TestBean3() {
}
public TestBean3(int id) {
super();
this.id = id;
}
private int id;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
}
}