diff --git a/src/main/java/org/junit/runners/Parameterized.java b/src/main/java/org/junit/runners/Parameterized.java
index 9b1cc0200210..2ad082c8d26d 100644
--- a/src/main/java/org/junit/runners/Parameterized.java
+++ b/src/main/java/org/junit/runners/Parameterized.java
@@ -1,11 +1,9 @@
package org.junit.runners;
-import java.lang.annotation.Annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
-import java.lang.reflect.Field;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Arrays;
@@ -13,11 +11,12 @@
import java.util.List;
import org.junit.runner.Runner;
-import org.junit.runner.notification.RunNotifier;
-import org.junit.runners.model.FrameworkField;
import org.junit.runners.model.FrameworkMethod;
import org.junit.runners.model.InitializationError;
-import org.junit.runners.model.Statement;
+import org.junit.runners.model.TestClass;
+import org.junit.runners.parameterized.BlockJUnit4ClassRunnerWithParametersFactory;
+import org.junit.runners.parameterized.ParametersRunnerFactory;
+import org.junit.runners.parameterized.TestWithParameters;
/**
* The custom runner Parameterized implements parameterized tests.
@@ -130,6 +129,36 @@
* }
*
*
+ *
Create different runners
+ *
+ * By default the {@code Parameterized} runner creates a slightly modified
+ * {@link BlockJUnit4ClassRunner} for each set of parameters. You can build an
+ * own {@code Parameterized} runner that creates another runner for each set of
+ * parameters. Therefore you have to build a {@link ParametersRunnerFactory}
+ * that creates a runner for each {@link TestWithParameters}. (
+ * {@code TestWithParameters} are bundling the parameters and the test name.)
+ * The factory must have a public zero-arg constructor.
+ *
+ *
+ * public class YourRunnerFactory implements ParameterizedRunnerFactory {
+ * public Runner createRunnerForTestWithParameters(TestWithParameters test)
+ * throws InitializationError {
+ * return YourRunner(test);
+ * }
+ * }
+ *
+ *
+ * Use the {@link UseParametersRunnerFactory} to tell the {@code Parameterized}
+ * runner that it should use your factory.
+ *
+ *
+ * @RunWith(Parameterized.class)
+ * @UseParametersRunnerFactory(YourRunnerFactory.class)
+ * public class YourTest {
+ * ...
+ * }
+ *
+ *
* @since 4.0
*/
public class Parameterized extends Suite {
@@ -183,118 +212,24 @@ public class Parameterized extends Suite {
int value() default 0;
}
- protected class TestClassRunnerForParameters extends BlockJUnit4ClassRunner {
- private final Object[] fParameters;
-
- private final String fName;
-
- protected TestClassRunnerForParameters(Class> type, String pattern, int index, Object[] parameters) throws InitializationError {
- super(type);
-
- fParameters = parameters;
- fName = nameFor(pattern, index, parameters);
- }
-
- @Override
- public Object createTest() throws Exception {
- if (fieldsAreAnnotated()) {
- return createTestUsingFieldInjection();
- } else {
- return createTestUsingConstructorInjection();
- }
- }
-
- private Object createTestUsingConstructorInjection() throws Exception {
- return getTestClass().getOnlyConstructor().newInstance(fParameters);
- }
-
- private Object createTestUsingFieldInjection() throws Exception {
- List annotatedFieldsByParameter = getAnnotatedFieldsByParameter();
- if (annotatedFieldsByParameter.size() != fParameters.length) {
- throw new Exception("Wrong number of parameters and @Parameter fields." +
- " @Parameter fields counted: " + annotatedFieldsByParameter.size() + ", available parameters: " + fParameters.length + ".");
- }
- Object testClassInstance = getTestClass().getJavaClass().newInstance();
- for (FrameworkField each : annotatedFieldsByParameter) {
- Field field = each.getField();
- Parameter annotation = field.getAnnotation(Parameter.class);
- int index = annotation.value();
- try {
- field.set(testClassInstance, fParameters[index]);
- } catch (IllegalArgumentException iare) {
- throw new Exception(getTestClass().getName() + ": Trying to set " + field.getName() +
- " with the value " + fParameters[index] +
- " that is not the right type (" + fParameters[index].getClass().getSimpleName() + " instead of " +
- field.getType().getSimpleName() + ").", iare);
- }
- }
- return testClassInstance;
- }
-
- protected String nameFor(String pattern, int index, Object[] parameters) {
- String finalPattern = pattern.replaceAll("\\{index\\}", Integer.toString(index));
- String name = MessageFormat.format(finalPattern, parameters);
- return "[" + name + "]";
- }
-
- @Override
- protected String getName() {
- return fName;
- }
-
- @Override
- protected String testName(FrameworkMethod method) {
- return method.getName() + getName();
- }
-
- @Override
- protected void validateConstructor(List errors) {
- validateOnlyOneConstructor(errors);
- if (fieldsAreAnnotated()) {
- validateZeroArgConstructor(errors);
- }
- }
-
- @Override
- protected void validateFields(List errors) {
- super.validateFields(errors);
- if (fieldsAreAnnotated()) {
- List annotatedFieldsByParameter = getAnnotatedFieldsByParameter();
- int[] usedIndices = new int[annotatedFieldsByParameter.size()];
- for (FrameworkField each : annotatedFieldsByParameter) {
- int index = each.getField().getAnnotation(Parameter.class).value();
- if (index < 0 || index > annotatedFieldsByParameter.size() - 1) {
- errors.add(
- new Exception("Invalid @Parameter value: " + index + ". @Parameter fields counted: " +
- annotatedFieldsByParameter.size() + ". Please use an index between 0 and " +
- (annotatedFieldsByParameter.size() - 1) + ".")
- );
- } else {
- usedIndices[index]++;
- }
- }
- for (int index = 0; index < usedIndices.length; index++) {
- int numberOfUse = usedIndices[index];
- if (numberOfUse == 0) {
- errors.add(new Exception("@Parameter(" + index + ") is never used."));
- } else if (numberOfUse > 1) {
- errors.add(new Exception("@Parameter(" + index + ") is used more than once (" + numberOfUse + ")."));
- }
- }
- }
- }
-
- @Override
- protected Statement classBlock(RunNotifier notifier) {
- return childrenInvoker(notifier);
- }
-
- @Override
- protected Annotation[] getRunnerAnnotations() {
- return new Annotation[0];
- }
+ /**
+ * Add this annotation to your test class if you want to generate a special
+ * runner. You have to specify a {@link ParametersRunnerFactory} class that
+ * creates such runners. The factory must have a public zero-arg
+ * constructor.
+ */
+ @Retention(RetentionPolicy.RUNTIME)
+ @Target(ElementType.TYPE)
+ public @interface UseParametersRunnerFactory {
+ /**
+ * @return a {@link ParametersRunnerFactory} class (must have a default
+ * constructor)
+ */
+ Class extends ParametersRunnerFactory> value() default BlockJUnit4ClassRunnerWithParametersFactory.class;
}
+ private static final ParametersRunnerFactory DEFAULT_FACTORY = new BlockJUnit4ClassRunnerWithParametersFactory();
+
private static final List NO_RUNNERS = Collections.emptyList();
private final List fRunners;
@@ -304,9 +239,25 @@ protected Annotation[] getRunnerAnnotations() {
*/
public Parameterized(Class> klass) throws Throwable {
super(klass, NO_RUNNERS);
+ ParametersRunnerFactory runnerFactory = getParametersRunnerFactory(
+ klass);
Parameters parameters = getParametersMethod().getAnnotation(
Parameters.class);
- fRunners = Collections.unmodifiableList(createRunnersForParameters(allParameters(), parameters.name()));
+ fRunners = Collections.unmodifiableList(createRunnersForParameters(
+ allParameters(), parameters.name(), runnerFactory));
+ }
+
+ private ParametersRunnerFactory getParametersRunnerFactory(Class> klass)
+ throws InstantiationException, IllegalAccessException {
+ UseParametersRunnerFactory annotation = klass
+ .getAnnotation(UseParametersRunnerFactory.class);
+ if (annotation == null) {
+ return DEFAULT_FACTORY;
+ } else {
+ Class extends ParametersRunnerFactory> factoryClass = annotation
+ .value();
+ return factoryClass.newInstance();
+ }
}
@Override
@@ -314,16 +265,12 @@ protected List getChildren() {
return fRunners;
}
- private Runner createRunnerWithNotNormalizedParameters(String pattern,
- int index, Object parametersOrSingleParameter)
- throws InitializationError {
+ private TestWithParameters createTestWithNotNormalizedParameters(
+ String pattern, int index, Object parametersOrSingleParameter) {
Object[] parameters= (parametersOrSingleParameter instanceof Object[]) ? (Object[]) parametersOrSingleParameter
: new Object[] { parametersOrSingleParameter };
- return createRunner(pattern, index, parameters);
- }
-
- protected Runner createRunner(String pattern, int index, Object[] parameters) throws InitializationError {
- return new TestClassRunnerForParameters(getTestClass().getJavaClass(), pattern, index, parameters);
+ return createTestWithParameters(getTestClass(), pattern, index,
+ parameters);
}
@SuppressWarnings("unchecked")
@@ -351,20 +298,37 @@ private FrameworkMethod getParametersMethod() throws Exception {
+ getTestClass().getName());
}
- private List createRunnersForParameters(Iterable allParameters, String namePattern) throws Exception {
+ private List createRunnersForParameters(
+ Iterable allParameters, String namePattern,
+ ParametersRunnerFactory runnerFactory)
+ throws InitializationError,
+ Exception {
try {
- int i = 0;
- List children = new ArrayList();
- for (Object parametersOfSingleTest : allParameters) {
- children.add(createRunnerWithNotNormalizedParameters(
- namePattern, i++, parametersOfSingleTest));
+ List tests = createTestsForParameters(
+ allParameters, namePattern);
+ List runners = new ArrayList();
+ for (TestWithParameters test : tests) {
+ runners.add(runnerFactory
+ .createRunnerForTestWithParameters(test));
}
- return children;
+ return runners;
} catch (ClassCastException e) {
throw parametersMethodReturnedWrongType();
}
}
+ private List createTestsForParameters(
+ Iterable allParameters, String namePattern)
+ throws Exception {
+ int i = 0;
+ List children = new ArrayList();
+ for (Object parametersOfSingleTest : allParameters) {
+ children.add(createTestWithNotNormalizedParameters(namePattern,
+ i++, parametersOfSingleTest));
+ }
+ return children;
+ }
+
private Exception parametersMethodReturnedWrongType() throws Exception {
String className = getTestClass().getName();
String methodName = getParametersMethod().getName();
@@ -374,11 +338,12 @@ private Exception parametersMethodReturnedWrongType() throws Exception {
return new Exception(message);
}
- private List getAnnotatedFieldsByParameter() {
- return getTestClass().getAnnotatedFields(Parameter.class);
- }
-
- private boolean fieldsAreAnnotated() {
- return !getAnnotatedFieldsByParameter().isEmpty();
+ private static TestWithParameters createTestWithParameters(
+ TestClass testClass, String pattern, int index, Object[] parameters) {
+ String finalPattern = pattern.replaceAll("\\{index\\}",
+ Integer.toString(index));
+ String name = MessageFormat.format(finalPattern, parameters);
+ return new TestWithParameters("[" + name + "]", testClass,
+ Arrays.asList(parameters));
}
-}
\ No newline at end of file
+}
diff --git a/src/main/java/org/junit/runners/model/TestClass.java b/src/main/java/org/junit/runners/model/TestClass.java
index 6a265757eb86..e02ec9bb87db 100755
--- a/src/main/java/org/junit/runners/model/TestClass.java
+++ b/src/main/java/org/junit/runners/model/TestClass.java
@@ -252,6 +252,26 @@ public boolean isANonStaticInnerClass() {
return fClass.isMemberClass() && !isStatic(fClass.getModifiers());
}
+ @Override
+ public int hashCode() {
+ return (fClass == null) ? 0 : fClass.hashCode();
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ TestClass other = (TestClass) obj;
+ return fClass == other.fClass;
+ }
+
/**
* Compares two fields by its name.
*/
diff --git a/src/main/java/org/junit/runners/parameterized/BlockJUnit4ClassRunnerWithParameters.java b/src/main/java/org/junit/runners/parameterized/BlockJUnit4ClassRunnerWithParameters.java
new file mode 100644
index 000000000000..e1b47954d19a
--- /dev/null
+++ b/src/main/java/org/junit/runners/parameterized/BlockJUnit4ClassRunnerWithParameters.java
@@ -0,0 +1,143 @@
+package org.junit.runners.parameterized;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Field;
+import java.util.List;
+
+import org.junit.runner.notification.RunNotifier;
+import org.junit.runners.BlockJUnit4ClassRunner;
+import org.junit.runners.Parameterized.Parameter;
+import org.junit.runners.model.FrameworkField;
+import org.junit.runners.model.FrameworkMethod;
+import org.junit.runners.model.InitializationError;
+import org.junit.runners.model.Statement;
+
+/**
+ * A {@link BlockJUnit4ClassRunner} with parameters support. Parameters can be
+ * injected via constructor or into annotated fields.
+ */
+public class BlockJUnit4ClassRunnerWithParameters extends
+ BlockJUnit4ClassRunner {
+ private final Object[] fParameters;
+
+ private final String fName;
+
+ public BlockJUnit4ClassRunnerWithParameters(TestWithParameters test)
+ throws InitializationError {
+ super(test.getTestClass().getJavaClass());
+ fParameters = test.getParameters().toArray(
+ new Object[test.getParameters().size()]);
+ fName = test.getName();
+ }
+
+ @Override
+ public Object createTest() throws Exception {
+ if (fieldsAreAnnotated()) {
+ return createTestUsingFieldInjection();
+ } else {
+ return createTestUsingConstructorInjection();
+ }
+ }
+
+ private Object createTestUsingConstructorInjection() throws Exception {
+ return getTestClass().getOnlyConstructor().newInstance(fParameters);
+ }
+
+ private Object createTestUsingFieldInjection() throws Exception {
+ List annotatedFieldsByParameter = getAnnotatedFieldsByParameter();
+ if (annotatedFieldsByParameter.size() != fParameters.length) {
+ throw new Exception(
+ "Wrong number of parameters and @Parameter fields."
+ + " @Parameter fields counted: "
+ + annotatedFieldsByParameter.size()
+ + ", available parameters: " + fParameters.length
+ + ".");
+ }
+ Object testClassInstance = getTestClass().getJavaClass().newInstance();
+ for (FrameworkField each : annotatedFieldsByParameter) {
+ Field field = each.getField();
+ Parameter annotation = field.getAnnotation(Parameter.class);
+ int index = annotation.value();
+ try {
+ field.set(testClassInstance, fParameters[index]);
+ } catch (IllegalArgumentException iare) {
+ throw new Exception(getTestClass().getName()
+ + ": Trying to set " + field.getName()
+ + " with the value " + fParameters[index]
+ + " that is not the right type ("
+ + fParameters[index].getClass().getSimpleName()
+ + " instead of " + field.getType().getSimpleName()
+ + ").", iare);
+ }
+ }
+ return testClassInstance;
+ }
+
+ @Override
+ protected String getName() {
+ return fName;
+ }
+
+ @Override
+ protected String testName(FrameworkMethod method) {
+ return method.getName() + getName();
+ }
+
+ @Override
+ protected void validateConstructor(List errors) {
+ validateOnlyOneConstructor(errors);
+ if (fieldsAreAnnotated()) {
+ validateZeroArgConstructor(errors);
+ }
+ }
+
+ @Override
+ protected void validateFields(List errors) {
+ super.validateFields(errors);
+ if (fieldsAreAnnotated()) {
+ List annotatedFieldsByParameter = getAnnotatedFieldsByParameter();
+ int[] usedIndices = new int[annotatedFieldsByParameter.size()];
+ for (FrameworkField each : annotatedFieldsByParameter) {
+ int index = each.getField().getAnnotation(Parameter.class)
+ .value();
+ if (index < 0 || index > annotatedFieldsByParameter.size() - 1) {
+ errors.add(new Exception("Invalid @Parameter value: "
+ + index + ". @Parameter fields counted: "
+ + annotatedFieldsByParameter.size()
+ + ". Please use an index between 0 and "
+ + (annotatedFieldsByParameter.size() - 1) + "."));
+ } else {
+ usedIndices[index]++;
+ }
+ }
+ for (int index = 0; index < usedIndices.length; index++) {
+ int numberOfUse = usedIndices[index];
+ if (numberOfUse == 0) {
+ errors.add(new Exception("@Parameter(" + index
+ + ") is never used."));
+ } else if (numberOfUse > 1) {
+ errors.add(new Exception("@Parameter(" + index
+ + ") is used more than once (" + numberOfUse + ")."));
+ }
+ }
+ }
+ }
+
+ @Override
+ protected Statement classBlock(RunNotifier notifier) {
+ return childrenInvoker(notifier);
+ }
+
+ @Override
+ protected Annotation[] getRunnerAnnotations() {
+ return new Annotation[0];
+ }
+
+ private List getAnnotatedFieldsByParameter() {
+ return getTestClass().getAnnotatedFields(Parameter.class);
+ }
+
+ private boolean fieldsAreAnnotated() {
+ return !getAnnotatedFieldsByParameter().isEmpty();
+ }
+}
diff --git a/src/main/java/org/junit/runners/parameterized/BlockJUnit4ClassRunnerWithParametersFactory.java b/src/main/java/org/junit/runners/parameterized/BlockJUnit4ClassRunnerWithParametersFactory.java
new file mode 100644
index 000000000000..ae49ef4ba73b
--- /dev/null
+++ b/src/main/java/org/junit/runners/parameterized/BlockJUnit4ClassRunnerWithParametersFactory.java
@@ -0,0 +1,18 @@
+package org.junit.runners.parameterized;
+
+import org.junit.runner.Runner;
+import org.junit.runners.model.InitializationError;
+
+/**
+ * A {@link ParametersRunnerFactory} that creates
+ * {@link BlockJUnit4ClassRunnerWithParameters}.
+ *
+ * @since 4.12
+ */
+public class BlockJUnit4ClassRunnerWithParametersFactory implements
+ ParametersRunnerFactory {
+ public Runner createRunnerForTestWithParameters(TestWithParameters test)
+ throws InitializationError {
+ return new BlockJUnit4ClassRunnerWithParameters(test);
+ }
+}
diff --git a/src/main/java/org/junit/runners/parameterized/ParametersRunnerFactory.java b/src/main/java/org/junit/runners/parameterized/ParametersRunnerFactory.java
new file mode 100644
index 000000000000..16ea1f30e029
--- /dev/null
+++ b/src/main/java/org/junit/runners/parameterized/ParametersRunnerFactory.java
@@ -0,0 +1,21 @@
+package org.junit.runners.parameterized;
+
+import org.junit.runner.Runner;
+import org.junit.runners.model.InitializationError;
+
+/**
+ * A {@code ParameterizedRunnerFactory} creates a runner for a single
+ * {@link TestWithParameters}.
+ *
+ * @since 4.12
+ */
+public interface ParametersRunnerFactory {
+ /**
+ * Returns a runner for the specified {@link TestWithParameters}.
+ *
+ * @throws InitializationError
+ * if the runner could not be created.
+ */
+ Runner createRunnerForTestWithParameters(TestWithParameters test)
+ throws InitializationError;
+}
diff --git a/src/main/java/org/junit/runners/parameterized/TestWithParameters.java b/src/main/java/org/junit/runners/parameterized/TestWithParameters.java
new file mode 100644
index 000000000000..52dae5fa2557
--- /dev/null
+++ b/src/main/java/org/junit/runners/parameterized/TestWithParameters.java
@@ -0,0 +1,82 @@
+package org.junit.runners.parameterized;
+
+import static java.util.Collections.unmodifiableList;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.junit.runners.model.TestClass;
+
+/**
+ * A {@code TestWithParameters} keeps the data together that are needed for
+ * creating a runner for a single data set of a parameterized test. It has a
+ * name, the test class and a list of parameters.
+ *
+ * @since 4.12
+ */
+public class TestWithParameters {
+ private final String fName;
+
+ private final TestClass fTestClass;
+
+ private final List fParameters;
+
+ public TestWithParameters(String name, TestClass testClass,
+ List parameters) {
+ notNull(name, "The name is missing.");
+ notNull(testClass, "The test class is missing.");
+ notNull(parameters, "The parameters are missing.");
+ fName = name;
+ fTestClass = testClass;
+ fParameters = unmodifiableList(new ArrayList(parameters));
+ }
+
+ public String getName() {
+ return fName;
+ }
+
+ public TestClass getTestClass() {
+ return fTestClass;
+ }
+
+ public List getParameters() {
+ return fParameters;
+ }
+
+ @Override
+ public int hashCode() {
+ int prime = 14747;
+ int result = prime + fName.hashCode();
+ result = prime * result + fTestClass.hashCode();
+ return prime * result + fParameters.hashCode();
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ TestWithParameters other = (TestWithParameters) obj;
+ return fName.equals(other.fName)
+ && fParameters.equals(other.fParameters)
+ && fTestClass.equals(other.fTestClass);
+ }
+
+ @Override
+ public String toString() {
+ return fTestClass.getName() + " '" + fName + "' with parameters "
+ + fParameters;
+ }
+
+ private static void notNull(Object value, String message) {
+ if (value == null) {
+ throw new NullPointerException(message);
+ }
+ }
+}
diff --git a/src/test/java/org/junit/tests/running/classes/TestClassTest.java b/src/test/java/org/junit/runners/model/TestClassTest.java
similarity index 67%
rename from src/test/java/org/junit/tests/running/classes/TestClassTest.java
rename to src/test/java/org/junit/runners/model/TestClassTest.java
index 4a584d01468d..beb7ecebbf3d 100644
--- a/src/test/java/org/junit/tests/running/classes/TestClassTest.java
+++ b/src/test/java/org/junit/runners/model/TestClassTest.java
@@ -1,8 +1,11 @@
-package org.junit.tests.running.classes;
+package org.junit.runners.model;
import static org.hamcrest.CoreMatchers.hasItem;
import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
import java.util.List;
@@ -11,9 +14,6 @@
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.junit.rules.TestRule;
-import org.junit.runners.model.FrameworkField;
-import org.junit.runners.model.FrameworkMethod;
-import org.junit.runners.model.TestClass;
public class TestClassTest {
@@ -150,4 +150,55 @@ public void annotatedMethodValues() {
assertThat(values, hasItem("jupiter"));
assertThat(values.size(), is(1));
}
+
+ @Test
+ public void isEqualToTestClassThatWrapsSameJavaClass() {
+ TestClass testClass = new TestClass(DummyClass.class);
+ TestClass testClassThatWrapsSameJavaClass = new TestClass(
+ DummyClass.class);
+ assertTrue(testClass.equals(testClassThatWrapsSameJavaClass));
+ }
+
+ @Test
+ public void isEqualToTestClassThatWrapsNoJavaClassToo() {
+ TestClass testClass = new TestClass(null);
+ TestClass testClassThatWrapsNoJavaClassToo = new TestClass(null);
+ assertTrue(testClass.equals(testClassThatWrapsNoJavaClassToo));
+ }
+
+ @Test
+ public void isNotEqualToTestClassThatWrapsADifferentJavaClass() {
+ TestClass testClass = new TestClass(DummyClass.class);
+ TestClass testClassThatWrapsADifferentJavaClass = new TestClass(
+ AnotherDummyClass.class);
+ assertFalse(testClass.equals(testClassThatWrapsADifferentJavaClass));
+ }
+
+ @Test
+ public void isNotEqualToNull() {
+ TestClass testClass = new TestClass(DummyClass.class);
+ assertFalse(testClass.equals(null));
+ }
+
+ private static class DummyClass {
+ }
+
+ private static class AnotherDummyClass {
+ }
+
+ @Test
+ public void hasSameHashCodeAsTestClassThatWrapsSameJavaClass() {
+ TestClass testClass = new TestClass(DummyClass.class);
+ TestClass testClassThatWrapsSameJavaClass = new TestClass(
+ DummyClass.class);
+ assertEquals(testClass.hashCode(),
+ testClassThatWrapsSameJavaClass.hashCode());
+ }
+
+ @Test
+ public void hasHashCodeWithoutJavaClass() {
+ TestClass testClass = new TestClass(null);
+ testClass.hashCode();
+ // everything is fine if no exception is thrown.
+ }
}
diff --git a/src/test/java/org/junit/runners/parameterized/TestWithParametersTest.java b/src/test/java/org/junit/runners/parameterized/TestWithParametersTest.java
new file mode 100644
index 000000000000..b8156e9fbd7b
--- /dev/null
+++ b/src/test/java/org/junit/runners/parameterized/TestWithParametersTest.java
@@ -0,0 +1,137 @@
+package org.junit.runners.parameterized;
+
+import static java.util.Arrays.asList;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.rules.ExpectedException.none;
+
+import java.util.Arrays;
+import java.util.List;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.junit.runners.model.TestClass;
+
+public class TestWithParametersTest {
+ private static final String DUMMY_NAME = "dummy name";
+
+ private static final TestClass DUMMY_TEST_CLASS = new TestClass(
+ DummyClass.class);
+
+ private static final List DUMMY_PARAMETERS = Arrays
+ . asList("a", "b");
+
+ @Rule
+ public final ExpectedException thrown = none();
+
+ @Test
+ public void cannotBeCreatedWithoutAName() {
+ thrown.expect(NullPointerException.class);
+ thrown.expectMessage("The name is missing.");
+ new TestWithParameters(null, DUMMY_TEST_CLASS, DUMMY_PARAMETERS);
+ }
+
+ @Test
+ public void cannotBeCreatedWithoutTestClass() {
+ thrown.expect(NullPointerException.class);
+ thrown.expectMessage("The test class is missing.");
+ new TestWithParameters(DUMMY_NAME, null, DUMMY_PARAMETERS);
+ }
+
+ @Test
+ public void cannotBeCreatedWithoutParameters() {
+ thrown.expect(NullPointerException.class);
+ thrown.expectMessage("The parameters are missing.");
+ new TestWithParameters(DUMMY_NAME, DUMMY_TEST_CLASS,
+ (List) null);
+ }
+
+ @Test
+ public void doesNotAllowToModifyProvidedParameters() {
+ TestWithParameters test = new TestWithParameters(DUMMY_NAME,
+ DUMMY_TEST_CLASS, DUMMY_PARAMETERS);
+ thrown.expect(UnsupportedOperationException.class);
+ test.getParameters().set(0, "another parameter");
+ }
+
+ @Test
+ public void doesNotConsiderParametersWhichChangedAfterTestInstantiation() {
+ List parameters = Arrays. asList("dummy parameter");
+ TestWithParameters test = new TestWithParameters(DUMMY_NAME,
+ DUMMY_TEST_CLASS, parameters);
+ parameters.set(0, "another parameter");
+ assertEquals(asList("dummy parameter"), test.getParameters());
+ }
+
+ @Test
+ public void isEqualToTestWithSameNameAndTestClassAndParameters() {
+ TestWithParameters firstTest = new TestWithParameters(DUMMY_NAME,
+ new TestClass(DummyClass.class), Arrays. asList("a",
+ "b"));
+ TestWithParameters secondTest = new TestWithParameters(DUMMY_NAME,
+ new TestClass(DummyClass.class), Arrays. asList("a",
+ "b"));
+ assertEquals(firstTest, secondTest);
+ }
+
+ @Test
+ public void isNotEqualToTestWithDifferentName() {
+ TestWithParameters firstTest = new TestWithParameters("name",
+ DUMMY_TEST_CLASS, DUMMY_PARAMETERS);
+ TestWithParameters secondTest = new TestWithParameters("another name",
+ DUMMY_TEST_CLASS, DUMMY_PARAMETERS);
+ assertNotEquals(firstTest, secondTest);
+ }
+
+ @Test
+ public void isNotEqualToTestWithDifferentTestClass() {
+ TestWithParameters firstTest = new TestWithParameters(DUMMY_NAME,
+ new TestClass(DummyClass.class), DUMMY_PARAMETERS);
+ TestWithParameters secondTest = new TestWithParameters(DUMMY_NAME,
+ new TestClass(AnotherDummyClass.class), DUMMY_PARAMETERS);
+ assertNotEquals(firstTest, secondTest);
+ }
+
+ @Test
+ public void isNotEqualToTestWithDifferentParameters() {
+ TestWithParameters firstTest = new TestWithParameters(DUMMY_NAME,
+ DUMMY_TEST_CLASS, Arrays. asList("a"));
+ TestWithParameters secondTest = new TestWithParameters(DUMMY_NAME,
+ DUMMY_TEST_CLASS, Arrays. asList("b"));
+ assertNotEquals(firstTest, secondTest);
+ }
+
+ @Test
+ public void isNotEqualToObjectWithDifferentClass() {
+ TestWithParameters test = new TestWithParameters(DUMMY_NAME,
+ DUMMY_TEST_CLASS, DUMMY_PARAMETERS);
+ assertNotEquals(test, new Integer(3));
+ }
+
+ @Test
+ public void hasSameHashCodeAsEqualTest() {
+ TestWithParameters firstTest = new TestWithParameters(DUMMY_NAME,
+ DUMMY_TEST_CLASS, DUMMY_PARAMETERS);
+ TestWithParameters secondTest = new TestWithParameters(DUMMY_NAME,
+ DUMMY_TEST_CLASS, DUMMY_PARAMETERS);
+ assertEquals(firstTest.hashCode(), secondTest.hashCode());
+ }
+
+ @Test
+ public void hasMeaningfulToString() {
+ TestWithParameters test = new TestWithParameters("name", new TestClass(
+ DummyClass.class), Arrays. asList("first parameter",
+ "second parameter"));
+ assertEquals(
+ "Wrong toString().",
+ "org.junit.runners.parameterized.TestWithParametersTest$DummyClass 'name' with parameters [first parameter, second parameter]",
+ test.toString());
+ }
+
+ private static class DummyClass {
+ }
+
+ private static class AnotherDummyClass {
+ }
+}
diff --git a/src/test/java/org/junit/tests/AllTests.java b/src/test/java/org/junit/tests/AllTests.java
index ad356a737454..beab4d215d0c 100644
--- a/src/test/java/org/junit/tests/AllTests.java
+++ b/src/test/java/org/junit/tests/AllTests.java
@@ -17,6 +17,8 @@
import org.junit.runners.Suite.SuiteClasses;
import org.junit.runners.model.FrameworkFieldTest;
import org.junit.runners.model.FrameworkMethodTest;
+import org.junit.runners.model.TestClassTest;
+import org.junit.runners.parameterized.TestWithParametersTest;
import org.junit.tests.assertion.AssertionTest;
import org.junit.tests.assertion.ComparisonFailureTest;
import org.junit.tests.assertion.MultipleFailureExceptionTest;
@@ -85,7 +87,6 @@
import org.junit.tests.running.classes.ParentRunnerTest;
import org.junit.tests.running.classes.RunWithTest;
import org.junit.tests.running.classes.SuiteTest;
-import org.junit.tests.running.classes.TestClassTest;
import org.junit.tests.running.classes.UseSuiteAsASuperclassTest;
import org.junit.tests.running.core.CommandLineTest;
import org.junit.tests.running.core.JUnitCoreReturnsCorrectExitCodeTest;
@@ -202,7 +203,8 @@
FrameworkFieldTest.class,
FrameworkMethodTest.class,
FailOnTimeoutTest.class,
- JUnitCoreTest.class
+ JUnitCoreTest.class,
+ TestWithParametersTest.class
})
public class AllTests {
public static Test suite() {
diff --git a/src/test/java/org/junit/tests/running/classes/ParameterizedTestTest.java b/src/test/java/org/junit/tests/running/classes/ParameterizedTestTest.java
index ea793ff8db64..672fe13a1808 100644
--- a/src/test/java/org/junit/tests/running/classes/ParameterizedTestTest.java
+++ b/src/test/java/org/junit/tests/running/classes/ParameterizedTestTest.java
@@ -25,7 +25,10 @@
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameter;
import org.junit.runners.Parameterized.Parameters;
+import org.junit.runners.Parameterized.UseParametersRunnerFactory;
import org.junit.runners.model.InitializationError;
+import org.junit.runners.parameterized.ParametersRunnerFactory;
+import org.junit.runners.parameterized.TestWithParameters;
public class ParameterizedTestTest {
@RunWith(Parameterized.class)
@@ -307,12 +310,10 @@ public void aTest() {
}
@Test
- public void meaningfulFailureWhenParametersNotPublic() throws Exception {
- Result result = JUnitCore.runClasses(ProtectedParametersTest.class);
- String expected = String.format(
- "No public static parameters method on class %s",
- ProtectedParametersTest.class.getName());
- assertEquals(expected, result.getFailures().get(0).getMessage());
+ public void meaningfulFailureWhenParametersNotPublic() {
+ assertTestCreatesSingleFailureWithMessage(ProtectedParametersTest.class,
+ "No public static parameters method on class "
+ + ProtectedParametersTest.class.getName());
}
@RunWith(Parameterized.class)
@@ -430,4 +431,42 @@ public void runsForEverySingleArgumentOfIterable() {
.runClasses(SingleArgumentTestWithIterable.class);
assertEquals(2, result.getRunCount());
}
+
+ static public class ExceptionThrowingRunnerFactory implements
+ ParametersRunnerFactory {
+ public Runner createRunnerForTestWithParameters(TestWithParameters test)
+ throws InitializationError {
+ throw new InitializationError(
+ "Called ExceptionThrowingRunnerFactory.");
+ }
+ }
+
+ @RunWith(Parameterized.class)
+ @UseParametersRunnerFactory(ExceptionThrowingRunnerFactory.class)
+ static public class TestWithUseParametersRunnerFactoryAnnotation {
+ @Parameters
+ public static Iterable extends Object> data() {
+ return asList("single test");
+ }
+
+ public TestWithUseParametersRunnerFactoryAnnotation(Object argument) {
+ }
+
+ @Test
+ public void aTest() {
+ }
+ }
+
+ @Test
+ public void usesParametersRunnerFactoryThatWasSpecifiedByAnnotation() {
+ assertTestCreatesSingleFailureWithMessage(
+ TestWithUseParametersRunnerFactoryAnnotation.class,
+ "Called ExceptionThrowingRunnerFactory.");
+ }
+
+ private void assertTestCreatesSingleFailureWithMessage(Class> test, String message) {
+ Result result = JUnitCore.runClasses(test);
+ assertEquals(1, result.getFailures().size());
+ assertEquals(message, result.getFailures().get(0).getMessage());
+ }
}
\ No newline at end of file