package org.javersion.reflect; import static org.assertj.core.api.Assertions.assertThat; import static org.javersion.reflect.TypeDescriptors.DEFAULT; import java.lang.annotation.Annotation; import java.lang.reflect.Method; import java.lang.reflect.Parameter; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import org.junit.Test; import com.google.common.collect.ImmutableSet; import nl.jqno.equalsverifier.EqualsVerifier; public class MethodDescriptorTest { static class MySuperClass<T> { Set<T> method(T first, @Param("rest") Set<T> second) { return null; } } static class MyClass<T> extends MySuperClass<T> { @Deprecated @Override Set<T> method(T first, @Param("rest") Set<T> second) { second.add(first); return second; } @SuppressWarnings("unused") private void privateMethod() {} } @SuppressWarnings("unused") private MyClass<Integer> myClass; @Test public void return_type() { MethodDescriptor method = getMethodDescriptor(); TypeDescriptor returnType = method.getReturnType(); assertThat(returnType.getRawType()).isEqualTo(Set.class); assertThat(returnType.resolveGenericParameter(Set.class, 0).getRawType()).isEqualTo(Integer.class); } @Test public void first_parameter_type() { MethodDescriptor method = getMethodDescriptor(); ParameterDescriptor parameter = method.getParameters().get(0); assertThat(parameter.getType().getRawType()).isEqualTo(Integer.class); } @Test public void second_parameter_type() { MethodDescriptor method = getMethodDescriptor(); ParameterDescriptor parameter = method.getParameters().get(1); TypeDescriptor type = parameter.getType(); assertThat(type.getRawType()).isEqualTo(Set.class); assertThat(type.resolveGenericParameter(Set.class, 0).getRawType()).isEqualTo(Integer.class); } @Test public void first_parameter_name() { MethodDescriptor method = getMethodDescriptor(); ParameterDescriptor parameter = method.getParameters().get(0); assertThat(parameter.getName()).isEqualTo("first"); } @Test public void second_parameter_name() { MethodDescriptor method = getMethodDescriptor(); ParameterDescriptor parameter = method.getParameters().get(1); assertThat(parameter.getName()).isEqualTo("rest"); } @Test public void invoke() { MyClass<Integer> myClass = new MyClass<>(); MethodDescriptor method = getMethodDescriptor(); @SuppressWarnings("unchecked") Set<Integer> result = (Set<Integer>) method.invoke(myClass, 123, new HashSet<>()); assertThat(result).isEqualTo(ImmutableSet.of(123)); } @Test public void identity() { Map<MethodSignature, MethodDescriptor> methods = getTypeDescriptor().getMethods(); EqualsVerifier.forClass(MethodDescriptor.class) .withPrefabValues(Method.class, methods.get(new MethodSignature("equals", Object.class)).getElement(), methods.get(new MethodSignature("hashCode")).getElement()) .verify(); } @Test public void parameter_identity() { List<ParameterDescriptor> parameters = getMethodDescriptor().getParameters(); EqualsVerifier.forClass(ParameterDescriptor.class) .withPrefabValues(Parameter.class, parameters.get(0).getElement(), parameters.get(1).getElement()) .verify(); } @Test(expected = IllegalArgumentException.class) public void invoke_without_parameters() { MyClass<Integer> myClass = new MyClass<>(); getMethodDescriptor().invoke(myClass); } @Test(expected = NullPointerException.class) public void invoke_without_object() { getMethodDescriptor().invoke(null, 123, new HashSet<>()); } @Test public void method_name() { assertThat(getMethodDescriptor().getName()).isEqualTo("method"); } @Test public void applies() { assertThat(getMethodDescriptor().applies(getTypeDescriptor())).isTrue(); assertThat(getMethodDescriptor().applies(DEFAULT.get(MethodDescriptorTest.class))).isFalse(); } @Test(expected = ReflectionException.class) public void illegal_access() { MethodDescriptor method = getTypeDescriptor().getMethods().get(new MethodSignature("privateMethod")); try { method.getElement().setAccessible(false); method.invoke(null, 123, new HashSet<>()); } finally { method.getElement().setAccessible(true); } } @Test public void method_annotations() { MethodDescriptor method = getMethodDescriptor(); method.hasAnnotation(Deprecated.class); assertThat(method.getAnnotation(Deprecated.class)).isInstanceOf(Deprecated.class); List<Annotation> annotations = method.getAnnotations(); assertThat(annotations).hasSize(1); assertThat(annotations.get(0)).isInstanceOf(Deprecated.class); } @Test public void to_string() { String str = getMethodDescriptor().toString(); assertThat(str).isEqualTo("MethodDescriptorTest$MyClass.method(Integer,Set)"); } @Test public void MethodSignature_toString() { String str = new MethodSignature(getMethodDescriptor().getElement()).toString(); assertThat(str).isEqualTo("method(Object,Set)"); } private static MethodDescriptor getMethodDescriptor() { return getTypeDescriptor().getMethods().get(new MethodSignature("method", Object.class, Set.class)); } private static TypeDescriptor getTypeDescriptor() { TypeDescriptor type = DEFAULT.get(MethodDescriptorTest.class); FieldDescriptor myClassField = type.getField("myClass"); return myClassField.getType(); } }