1 package org.junit.internal.builders; 2 3 import org.junit.runner.RunWith; 4 import org.junit.runner.Runner; 5 import org.junit.runners.model.InitializationError; 6 import org.junit.runners.model.RunnerBuilder; 7 8 import java.lang.reflect.Modifier; 9 10 11 /** 12 * The {@code AnnotatedBuilder} is a strategy for constructing runners for test class that have been annotated with the 13 * {@code @RunWith} annotation. All tests within this class will be executed using the runner that was specified within 14 * the annotation. 15 * <p> 16 * If a runner supports inner member classes, the member classes will inherit the runner from the enclosing class, e.g.: 17 * <pre> 18 * @RunWith(MyRunner.class) 19 * public class MyTest { 20 * // some tests might go here 21 * 22 * public class MyMemberClass { 23 * @Test 24 * public void thisTestRunsWith_MyRunner() { 25 * // some test logic 26 * } 27 * 28 * // some more tests might go here 29 * } 30 * 31 * @RunWith(AnotherRunner.class) 32 * public class AnotherMemberClass { 33 * // some tests might go here 34 * 35 * public class DeepInnerClass { 36 * @Test 37 * public void thisTestRunsWith_AnotherRunner() { 38 * // some test logic 39 * } 40 * } 41 * 42 * public class DeepInheritedClass extends SuperTest { 43 * @Test 44 * public void thisTestRunsWith_SuperRunner() { 45 * // some test logic 46 * } 47 * } 48 * } 49 * } 50 * 51 * @RunWith(SuperRunner.class) 52 * public class SuperTest { 53 * // some tests might go here 54 * } 55 * </pre> 56 * The key points to note here are: 57 * <ul> 58 * <li>If there is no RunWith annotation, no runner will be created.</li> 59 * <li>The resolve step is inside-out, e.g. the closest RunWith annotation wins</li> 60 * <li>RunWith annotations are inherited and work as if the class was annotated itself.</li> 61 * <li>The default JUnit runner does not support inner member classes, 62 * so this is only valid for custom runners that support inner member classes.</li> 63 * <li>Custom runners with support for inner classes may or may not support RunWith annotations for member 64 * classes. Please refer to the custom runner documentation.</li> 65 * </ul> 66 * 67 * @see org.junit.runners.model.RunnerBuilder 68 * @see org.junit.runner.RunWith 69 * @since 4.0 70 */ 71 public class AnnotatedBuilder extends RunnerBuilder { 72 private static final String CONSTRUCTOR_ERROR_FORMAT = "Custom runner class %s should have a public constructor with signature %s(Class testClass)"; 73 74 private final RunnerBuilder suiteBuilder; 75 AnnotatedBuilder(RunnerBuilder suiteBuilder)76 public AnnotatedBuilder(RunnerBuilder suiteBuilder) { 77 this.suiteBuilder = suiteBuilder; 78 } 79 80 @Override runnerForClass(Class<?> testClass)81 public Runner runnerForClass(Class<?> testClass) throws Exception { 82 for (Class<?> currentTestClass = testClass; currentTestClass != null; 83 currentTestClass = getEnclosingClassForNonStaticMemberClass(currentTestClass)) { 84 RunWith annotation = currentTestClass.getAnnotation(RunWith.class); 85 if (annotation != null) { 86 return buildRunner(annotation.value(), testClass); 87 } 88 } 89 90 return null; 91 } 92 getEnclosingClassForNonStaticMemberClass(Class<?> currentTestClass)93 private Class<?> getEnclosingClassForNonStaticMemberClass(Class<?> currentTestClass) { 94 if (currentTestClass.isMemberClass() && !Modifier.isStatic(currentTestClass.getModifiers())) { 95 return currentTestClass.getEnclosingClass(); 96 } else { 97 return null; 98 } 99 } 100 buildRunner(Class<? extends Runner> runnerClass, Class<?> testClass)101 public Runner buildRunner(Class<? extends Runner> runnerClass, 102 Class<?> testClass) throws Exception { 103 try { 104 return runnerClass.getConstructor(Class.class).newInstance(testClass); 105 } catch (NoSuchMethodException e) { 106 try { 107 return runnerClass.getConstructor(Class.class, 108 RunnerBuilder.class).newInstance(testClass, suiteBuilder); 109 } catch (NoSuchMethodException e2) { 110 String simpleName = runnerClass.getSimpleName(); 111 throw new InitializationError(String.format( 112 CONSTRUCTOR_ERROR_FORMAT, simpleName, simpleName)); 113 } 114 } 115 } 116 }