diff --git a/src/main/java/org/junit/runners/Parameterized.java b/src/main/java/org/junit/runners/Parameterized.java index cc7c804f4daa..9a6d4c3edbb8 100644 --- a/src/main/java/org/junit/runners/Parameterized.java +++ b/src/main/java/org/junit/runners/Parameterized.java @@ -217,6 +217,27 @@ public class Parameterized extends Suite { int value() default 0; } + /** + * Annotation for fields of the test class which will be initialized by the + * method annotated by StaticParameter. + * It can be used to initialize static fields. + * Index range must start at 0. + * Default value is 0. + */ + @Retention(RetentionPolicy.RUNTIME) + @Target(ElementType.FIELD) + public static @interface StaticParameter { + /** + * Method that returns the index of the parameter in the array + * returned by the method annotated by StaticParameter. + * Index range must start at 0. + * Default value is 0. + * + * @return the index of the parameter. + */ + int value() default 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 diff --git a/src/main/java/org/junit/runners/parameterized/BlockJUnit4ClassRunnerWithParameters.java b/src/main/java/org/junit/runners/parameterized/BlockJUnit4ClassRunnerWithParameters.java index ffed4beaf6bb..7053f3adda1e 100644 --- a/src/main/java/org/junit/runners/parameterized/BlockJUnit4ClassRunnerWithParameters.java +++ b/src/main/java/org/junit/runners/parameterized/BlockJUnit4ClassRunnerWithParameters.java @@ -2,12 +2,15 @@ import java.lang.annotation.Annotation; import java.lang.reflect.Field; +import java.lang.reflect.Modifier; +import java.util.ArrayList; import java.util.List; import org.junit.runner.RunWith; import org.junit.runner.notification.RunNotifier; import org.junit.runners.BlockJUnit4ClassRunner; import org.junit.runners.Parameterized.Parameter; +import org.junit.runners.Parameterized.StaticParameter; import org.junit.runners.model.FrameworkField; import org.junit.runners.model.FrameworkMethod; import org.junit.runners.model.InitializationError; @@ -55,7 +58,9 @@ private Object createTestUsingConstructorInjection() throws Exception { private Object createTestUsingFieldInjection() throws Exception { List annotatedFieldsByParameter = getAnnotatedFieldsByParameter(); - if (annotatedFieldsByParameter.size() != parameters.length) { + List annotatedFieldsByStaticParameter = getAnnotatedFieldsByStaticParameter(); + + if (annotatedFieldsByParameter.size() + annotatedFieldsByStaticParameter.size() != parameters.length) { throw new Exception( "Wrong number of parameters and @Parameter fields." + " @Parameter fields counted: " @@ -63,6 +68,26 @@ private Object createTestUsingFieldInjection() throws Exception { + ", available parameters: " + parameters.length + "."); } + + // Static parameters + for (FrameworkField each : annotatedFieldsByStaticParameter) { + Field field = each.getField(); + StaticParameter annotation = field.getAnnotation(StaticParameter.class); + int index = annotation.value(); + try { + field.set(null, parameters[index]); + } catch (IllegalArgumentException iare) { + throw new Exception(getTestClass().getName() + + ": Trying to set " + field.getName() + + " with the value " + parameters[index] + + " that is not the right type (" + + parameters[index].getClass().getSimpleName() + + " instead of " + field.getType().getSimpleName() + + ").", iare); + } + } + + // Non-static parameters Object testClassInstance = getTestClass().getJavaClass().newInstance(); for (FrameworkField each : annotatedFieldsByParameter) { Field field = each.getField(); @@ -105,17 +130,38 @@ protected void validateConstructor(List errors) { protected void validateFields(List errors) { super.validateFields(errors); if (getInjectionType() == InjectionType.FIELD) { - 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() + List parametricFields = new ArrayList(); + parametricFields.addAll(getAnnotatedFieldsByParameter()); + parametricFields.addAll(getAnnotatedFieldsByStaticParameter()); + + int[] usedIndices = new int[parametricFields.size()]; + for (FrameworkField each : parametricFields) { + int index = -1; + Field annotatedField = each.getField(); + if (Modifier.isStatic(annotatedField.getModifiers())) { + StaticParameter staticParam = annotatedField.getAnnotation(StaticParameter.class); + if (staticParam == null) { + errors.add(new Exception("Invalid @Parameter annotation on the static field: " + + annotatedField.getName() + ". It should be @StaticParameter.")); + } else { + index = staticParam.value(); + } + + } else { + Parameter param = annotatedField.getAnnotation(Parameter.class); + if (param == null) { + errors.add(new Exception("Invalid @StaticParameter annotation on the field: " + + annotatedField.getName() + ". It should be @Parameter.")); + } else { + index = param.value(); + } + } + if (index < 0 || index > parametricFields.size() - 1) { + errors.add(new Exception("Invalid @Parameter or @StaticParameter value: " + + index + ". parametric fields counted: " + + parametricFields.size() + ". Please use an index between 0 and " - + (annotatedFieldsByParameter.size() - 1) + ".")); + + (parametricFields.size() - 1) + ".")); } else { usedIndices[index]++; } @@ -123,11 +169,11 @@ protected void validateFields(List errors) { for (int index = 0; index < usedIndices.length; index++) { int numberOfUse = usedIndices[index]; if (numberOfUse == 0) { - errors.add(new Exception("@Parameter(" + index - + ") is never used.")); + 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 + ").")); + errors.add(new Exception("Parameter " + index + + " is used more than once (" + numberOfUse + ").")); } } } @@ -152,6 +198,10 @@ protected Annotation[] getRunnerAnnotations() { return annotationsWithoutRunWith; } + private List getAnnotatedFieldsByStaticParameter() { + return getTestClass().getAnnotatedFields(StaticParameter.class); + } + private List getAnnotatedFieldsByParameter() { return getTestClass().getAnnotatedFields(Parameter.class); } @@ -165,6 +215,6 @@ private InjectionType getInjectionType() { } private boolean fieldsAreAnnotated() { - return !getAnnotatedFieldsByParameter().isEmpty(); + return !getAnnotatedFieldsByParameter().isEmpty() || !getAnnotatedFieldsByStaticParameter().isEmpty(); } }