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