| 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(); |
| } |
| } |