1package org.junit.runners.model; 2 3import java.lang.annotation.Annotation; 4import java.lang.reflect.InvocationTargetException; 5import java.lang.reflect.Method; 6import java.lang.reflect.Modifier; 7import java.lang.reflect.Type; 8import java.util.List; 9 10import org.junit.internal.runners.model.ReflectiveCallable; 11 12/** 13 * Represents a method on a test class to be invoked at the appropriate point in 14 * test execution. These methods are usually marked with an annotation (such as 15 * {@code @Test}, {@code @Before}, {@code @After}, {@code @BeforeClass}, 16 * {@code @AfterClass}, etc.) 17 */ 18public class FrameworkMethod extends FrameworkMember<FrameworkMethod> { 19 final Method fMethod; 20 21 /** 22 * Returns a new {@code FrameworkMethod} for {@code method} 23 */ 24 public FrameworkMethod(Method method) { 25 fMethod= method; 26 } 27 28 /** 29 * Returns the underlying Java method 30 */ 31 public Method getMethod() { 32 return fMethod; 33 } 34 35 /** 36 * Returns the result of invoking this method on {@code target} with 37 * parameters {@code params}. {@link InvocationTargetException}s thrown are 38 * unwrapped, and their causes rethrown. 39 */ 40 public Object invokeExplosively(final Object target, final Object... params) 41 throws Throwable { 42 return new ReflectiveCallable() { 43 @Override 44 protected Object runReflectiveCall() throws Throwable { 45 return fMethod.invoke(target, params); 46 } 47 }.run(); 48 } 49 50 /** 51 * Returns the method's name 52 */ 53 public String getName() { 54 return fMethod.getName(); 55 } 56 57 /** 58 * Adds to {@code errors} if this method: 59 * <ul> 60 * <li>is not public, or 61 * <li>takes parameters, or 62 * <li>returns something other than void, or 63 * <li>is static (given {@code isStatic is false}), or 64 * <li>is not static (given {@code isStatic is true}). 65 */ 66 public void validatePublicVoidNoArg(boolean isStatic, List<Throwable> errors) { 67 validatePublicVoid(isStatic, errors); 68 if (fMethod.getParameterTypes().length != 0) 69 errors.add(new Exception("Method " + fMethod.getName() + " should have no parameters")); 70 } 71 72 73 /** 74 * Adds to {@code errors} if this method: 75 * <ul> 76 * <li>is not public, or 77 * <li>returns something other than void, or 78 * <li>is static (given {@code isStatic is false}), or 79 * <li>is not static (given {@code isStatic is true}). 80 */ 81 public void validatePublicVoid(boolean isStatic, List<Throwable> errors) { 82 if (Modifier.isStatic(fMethod.getModifiers()) != isStatic) { 83 String state= isStatic ? "should" : "should not"; 84 errors.add(new Exception("Method " + fMethod.getName() + "() " + state + " be static")); 85 } 86 if (!Modifier.isPublic(fMethod.getDeclaringClass().getModifiers())) 87 errors.add(new Exception("Class " + fMethod.getDeclaringClass().getName() + " should be public")); 88 if (!Modifier.isPublic(fMethod.getModifiers())) 89 errors.add(new Exception("Method " + fMethod.getName() + "() should be public")); 90 if (fMethod.getReturnType() != Void.TYPE) 91 errors.add(new Exception("Method " + fMethod.getName() + "() should be void")); 92 } 93 94 public void validateNoTypeParametersOnArgs(List<Throwable> errors) { 95 new NoGenericTypeParametersValidator(fMethod).validate(errors); 96 } 97 98 @Override 99 public boolean isShadowedBy(FrameworkMethod other) { 100 if (!other.getName().equals(getName())) 101 return false; 102 if (other.getParameterTypes().length != getParameterTypes().length) 103 return false; 104 for (int i= 0; i < other.getParameterTypes().length; i++) 105 if (!other.getParameterTypes()[i].equals(getParameterTypes()[i])) 106 return false; 107 return true; 108 } 109 110 @Override 111 public boolean equals(Object obj) { 112 if (!FrameworkMethod.class.isInstance(obj)) 113 return false; 114 return ((FrameworkMethod) obj).fMethod.equals(fMethod); 115 } 116 117 @Override 118 public int hashCode() { 119 return fMethod.hashCode(); 120 } 121 122 /** 123 * Returns true iff this is a no-arg method that returns a value assignable 124 * to {@code type} 125 * 126 * @deprecated This is used only by the Theories runner, and does not 127 * use all the generic type info that it ought to. It will be replaced 128 * with a forthcoming ParameterSignature#canAcceptResultOf(FrameworkMethod) 129 * once Theories moves to junit-contrib. 130 */ 131 @Deprecated 132 public boolean producesType(Type type) { 133 return getParameterTypes().length == 0 && type instanceof Class<?> 134 && ((Class<?>) type).isAssignableFrom(fMethod.getReturnType()); 135 } 136 137 private Class<?>[] getParameterTypes() { 138 return fMethod.getParameterTypes(); 139 } 140 141 /** 142 * Returns the annotations on this method 143 */ 144 @Override 145 public Annotation[] getAnnotations() { 146 return fMethod.getAnnotations(); 147 } 148 149 /** 150 * Returns the annotation of type {@code annotationType} on this method, if 151 * one exists. 152 */ 153 public <T extends Annotation> T getAnnotation(Class<T> annotationType) { 154 return fMethod.getAnnotation(annotationType); 155 } 156} 157