diff options
Diffstat (limited to 'src/main/java/org/junit/runners/parameterized/BlockJUnit4ClassRunnerWithParameters.java')
-rw-r--r-- | src/main/java/org/junit/runners/parameterized/BlockJUnit4ClassRunnerWithParameters.java | 143 |
1 files changed, 143 insertions, 0 deletions
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 0000000..1c49f84 --- /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[] parameters; + + private final String name; + + public BlockJUnit4ClassRunnerWithParameters(TestWithParameters test) + throws InitializationError { + super(test.getTestClass().getJavaClass()); + parameters = test.getParameters().toArray( + new Object[test.getParameters().size()]); + name = test.getName(); + } + + @Override + public Object createTest() throws Exception { + if (fieldsAreAnnotated()) { + return createTestUsingFieldInjection(); + } else { + return createTestUsingConstructorInjection(); + } + } + + private Object createTestUsingConstructorInjection() throws Exception { + return getTestClass().getOnlyConstructor().newInstance(parameters); + } + + private Object createTestUsingFieldInjection() throws Exception { + List<FrameworkField> annotatedFieldsByParameter = getAnnotatedFieldsByParameter(); + if (annotatedFieldsByParameter.size() != parameters.length) { + throw new Exception( + "Wrong number of parameters and @Parameter fields." + + " @Parameter fields counted: " + + annotatedFieldsByParameter.size() + + ", available parameters: " + parameters.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, 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); + } + } + return testClassInstance; + } + + @Override + protected String getName() { + return name; + } + + @Override + protected String testName(FrameworkMethod method) { + return method.getName() + getName(); + } + + @Override + protected void validateConstructor(List<Throwable> errors) { + validateOnlyOneConstructor(errors); + if (fieldsAreAnnotated()) { + validateZeroArgConstructor(errors); + } + } + + @Override + protected void validateFields(List<Throwable> errors) { + super.validateFields(errors); + if (fieldsAreAnnotated()) { + List<FrameworkField> 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<FrameworkField> getAnnotatedFieldsByParameter() { + return getTestClass().getAnnotatedFields(Parameter.class); + } + + private boolean fieldsAreAnnotated() { + return !getAnnotatedFieldsByParameter().isEmpty(); + } +} |