diff --git a/src/main/java/org/junit/internal/builders/AllDefaultPossibilitiesBuilder.java b/src/main/java/org/junit/internal/builders/AllDefaultPossibilitiesBuilder.java
index 8704a546b5f2..7d2c0848022c 100644
--- a/src/main/java/org/junit/internal/builders/AllDefaultPossibilitiesBuilder.java
+++ b/src/main/java/org/junit/internal/builders/AllDefaultPossibilitiesBuilder.java
@@ -31,6 +31,7 @@ public Runner runnerForClass(Class> testClass) throws Throwable {
annotatedBuilder(),
suiteMethodBuilder(),
junit3Builder(),
+ defaultBuilder(),
junit4Builder());
for (RunnerBuilder each : builders) {
@@ -58,6 +59,10 @@ protected IgnoredBuilder ignoredBuilder() {
return new IgnoredBuilder();
}
+ protected RunnerBuilder defaultBuilder() {
+ return new NullBuilder();
+ }
+
protected RunnerBuilder suiteMethodBuilder() {
if (canUseSuiteMethod) {
return new SuiteMethodBuilder();
diff --git a/src/main/java/org/junit/internal/builders/AnnotatedBuilder.java b/src/main/java/org/junit/internal/builders/AnnotatedBuilder.java
index 04d7a683652f..3c163c7535a5 100644
--- a/src/main/java/org/junit/internal/builders/AnnotatedBuilder.java
+++ b/src/main/java/org/junit/internal/builders/AnnotatedBuilder.java
@@ -2,7 +2,6 @@
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;
@@ -69,8 +68,6 @@
* @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) {
@@ -83,7 +80,7 @@ public Runner runnerForClass(Class> testClass) throws Exception {
currentTestClass = getEnclosingClassForNonStaticMemberClass(currentTestClass)) {
RunWith annotation = currentTestClass.getAnnotation(RunWith.class);
if (annotation != null) {
- return buildRunner(annotation.value(), testClass);
+ return buildRunner(annotation.value(), testClass, suiteBuilder);
}
}
@@ -97,20 +94,4 @@ private Class> getEnclosingClassForNonStaticMemberClass(Class> currentTestCl
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));
- }
- }
- }
}
\ No newline at end of file
diff --git a/src/main/java/org/junit/internal/builders/DefaultBuilder.java b/src/main/java/org/junit/internal/builders/DefaultBuilder.java
new file mode 100644
index 000000000000..2bab5e7f8d17
--- /dev/null
+++ b/src/main/java/org/junit/internal/builders/DefaultBuilder.java
@@ -0,0 +1,18 @@
+package org.junit.internal.builders;
+
+import org.junit.runner.Runner;
+import org.junit.runners.model.RunnerBuilder;
+
+public class DefaultBuilder extends RunnerBuilder {
+ private Class extends Runner> defaultRunnerClass;
+ private RunnerBuilder suiteBuilder;
+
+ public DefaultBuilder(Class extends Runner> defaultRunnerClass, RunnerBuilder suiteBuilder) {
+ this.defaultRunnerClass = defaultRunnerClass;
+ this.suiteBuilder = suiteBuilder;
+ }
+
+ public Runner runnerForClass(Class> testClass) throws Throwable {
+ return buildRunner(defaultRunnerClass, testClass, suiteBuilder);
+ }
+}
diff --git a/src/main/java/org/junit/internal/requests/ClassRequest.java b/src/main/java/org/junit/internal/requests/ClassRequest.java
index 9000e2423b9f..d7c668599612 100644
--- a/src/main/java/org/junit/internal/requests/ClassRequest.java
+++ b/src/main/java/org/junit/internal/requests/ClassRequest.java
@@ -1,6 +1,7 @@
package org.junit.internal.requests;
import org.junit.internal.builders.AllDefaultPossibilitiesBuilder;
+import org.junit.internal.builders.DefaultBuilder;
import org.junit.internal.builders.SuiteMethodBuilder;
import org.junit.runner.Request;
import org.junit.runner.Runner;
@@ -17,10 +18,17 @@ public class ClassRequest extends Request {
private final Class> fTestClass;
private final boolean canUseSuiteMethod;
private volatile Runner runner;
+ private Class extends Runner> defaultRunnerClass;
- public ClassRequest(Class> testClass, boolean canUseSuiteMethod) {
+ public ClassRequest(Class> testClass, boolean canUseSuiteMethod,
+ Class extends Runner> defaultRunnerClass) {
this.fTestClass = testClass;
this.canUseSuiteMethod = canUseSuiteMethod;
+ this.defaultRunnerClass = defaultRunnerClass;
+ }
+
+ public ClassRequest(Class> testClass, boolean canUseSuiteMethod) {
+ this(testClass, canUseSuiteMethod, null);
}
public ClassRequest(Class> testClass) {
@@ -45,6 +53,14 @@ private class CustomAllDefaultPossibilitiesBuilder extends AllDefaultPossibiliti
protected RunnerBuilder suiteMethodBuilder() {
return new CustomSuiteMethodBuilder();
}
+
+ @Override
+ protected RunnerBuilder defaultBuilder() {
+ if (defaultRunnerClass != null) {
+ return new DefaultBuilder(defaultRunnerClass, this);
+ }
+ return super.defaultBuilder();
+ }
}
/*
diff --git a/src/main/java/org/junit/runner/Request.java b/src/main/java/org/junit/runner/Request.java
index 264489217f74..b15dd29fdf88 100644
--- a/src/main/java/org/junit/runner/Request.java
+++ b/src/main/java/org/junit/runner/Request.java
@@ -61,6 +61,19 @@ public static Request classWithoutSuiteMethod(Class> clazz) {
return new ClassRequest(clazz, false);
}
+ /**
+ * Create a Request
that, when processed, will run all the tests
+ * in a class. If the class does not set the runner to use, a runner of the given
+ * class will be used by default.
+ *
+ * @param clazz the class containing the tests
+ * @param defaultRunnerClass the class of the runner to use by default
+ * @return a Request
that will cause all tests in the class to be run
+ */
+ public static Request classWithDefaultRunner(Class> clazz, Class extends Runner> defaultRunnerClass) {
+ return new ClassRequest(clazz, true, defaultRunnerClass);
+ }
+
/**
* Create a Request
that, when processed, will run all the tests
* in a set of classes.
diff --git a/src/main/java/org/junit/runners/model/RunnerBuilder.java b/src/main/java/org/junit/runners/model/RunnerBuilder.java
index bc6f85f04813..6396a6b85adf 100644
--- a/src/main/java/org/junit/runners/model/RunnerBuilder.java
+++ b/src/main/java/org/junit/runners/model/RunnerBuilder.java
@@ -37,6 +37,8 @@
* @since 4.5
*/
public abstract class RunnerBuilder {
+ private static final String CONSTRUCTOR_ERROR_FORMAT = "Custom runner class %s should have a public constructor with signature %s(Class testClass)";
+
private final Set> parents = new HashSet>();
/**
@@ -80,6 +82,22 @@ void removeParent(Class> klass) {
parents.remove(klass);
}
+ public Runner buildRunner(Class extends Runner> runnerClass,
+ Class> testClass, RunnerBuilder suiteBuilder) 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));
+ }
+ }
+ }
+
/**
* Constructs and returns a list of Runners, one for each child class in
* {@code children}. Care is taken to avoid infinite recursion: