• 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.Modifier;
7 import java.lang.reflect.Type;
8 import java.util.List;
9 
10 import 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  */
18 public class FrameworkMethod extends FrameworkMember<FrameworkMethod> {
19 	final Method fMethod;
20 
21 	/**
22 	 * Returns a new {@code FrameworkMethod} for {@code method}
23 	 */
FrameworkMethod(Method method)24 	public FrameworkMethod(Method method) {
25 		fMethod= method;
26 	}
27 
28 	/**
29 	 * Returns the underlying Java method
30 	 */
getMethod()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 	 */
invokeExplosively(final Object target, final Object... params)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