org.junit.internal.builders.AnnotatedBuilder Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of virtdata-lib-realer Show documentation
Show all versions of virtdata-lib-realer Show documentation
With inspiration from other libraries
package org.junit.internal.builders;
import org.junit.runner.RunWith;
import org.junit.runner.Runner;
import org.junit.runners.model.InitializationError;
import org.junit.runners.model.RunnerBuilder;
import java.lang.reflect.Modifier;
/**
* The {@code AnnotatedBuilder} is a strategy for constructing runners for test class that have been annotated with the
* {@code @RunWith} annotation. All tests within this class will be executed using the runner that was specified within
* the annotation.
*
* If a runner supports inner member classes, the member classes will inherit the runner from the enclosing class, e.g.:
*
* @RunWith(MyRunner.class)
* public class MyTest {
* // some tests might go here
*
* public class MyMemberClass {
* @Test
* public void thisTestRunsWith_MyRunner() {
* // some test logic
* }
*
* // some more tests might go here
* }
*
* @RunWith(AnotherRunner.class)
* public class AnotherMemberClass {
* // some tests might go here
*
* public class DeepInnerClass {
* @Test
* public void thisTestRunsWith_AnotherRunner() {
* // some test logic
* }
* }
*
* public class DeepInheritedClass extends SuperTest {
* @Test
* public void thisTestRunsWith_SuperRunner() {
* // some test logic
* }
* }
* }
* }
*
* @RunWith(SuperRunner.class)
* public class SuperTest {
* // some tests might go here
* }
*
* The key points to note here are:
*
* - If there is no RunWith annotation, no runner will be created.
* - The resolve step is inside-out, e.g. the closest RunWith annotation wins
* - RunWith annotations are inherited and work as if the class was annotated itself.
* - The default JUnit runner does not support inner member classes,
* so this is only valid for custom runners that support inner member classes.
* - Custom runners with support for inner classes may or may not support RunWith annotations for member
* classes. Please refer to the custom runner documentation.
*
*
* @see org.junit.runners.model.RunnerBuilder
* @see org.junit.runner.RunWith
* @since 4.0
*/
public class AnnotatedBuilder extends RunnerBuilder {
private static final String CONSTRUCTOR_ERROR_FORMAT = "Custom runner class %s should have a public constructor with signature %s(Class testClass)";
private final RunnerBuilder suiteBuilder;
public AnnotatedBuilder(RunnerBuilder suiteBuilder) {
this.suiteBuilder = suiteBuilder;
}
@Override
public Runner runnerForClass(Class> testClass) throws Exception {
for (Class> currentTestClass = testClass; currentTestClass != null;
currentTestClass = getEnclosingClassForNonStaticMemberClass(currentTestClass)) {
RunWith annotation = currentTestClass.getAnnotation(RunWith.class);
if (annotation != null) {
return buildRunner(annotation.value(), testClass);
}
}
return null;
}
private Class> getEnclosingClassForNonStaticMemberClass(Class> currentTestClass) {
if (currentTestClass.isMemberClass() && !Modifier.isStatic(currentTestClass.getModifiers())) {
return currentTestClass.getEnclosingClass();
} else {
return null;
}
}
public Runner buildRunner(Class extends Runner> runnerClass,
Class> testClass) throws Exception {
try {
return runnerClass.getConstructor(Class.class).newInstance(testClass);
} catch (NoSuchMethodException e) {
try {
return runnerClass.getConstructor(Class.class,
RunnerBuilder.class).newInstance(testClass, suiteBuilder);
} catch (NoSuchMethodException e2) {
String simpleName = runnerClass.getSimpleName();
throw new InitializationError(String.format(
CONSTRUCTOR_ERROR_FORMAT, simpleName, simpleName));
}
}
}
}