Home | History | Annotate | Download | only in parameterized
      1 package org.junit.runners.parameterized;
      2 
      3 import java.lang.annotation.Annotation;
      4 import java.lang.reflect.Field;
      5 import java.util.List;
      6 
      7 import org.junit.runner.notification.RunNotifier;
      8 import org.junit.runners.BlockJUnit4ClassRunner;
      9 import org.junit.runners.Parameterized.Parameter;
     10 import org.junit.runners.model.FrameworkField;
     11 import org.junit.runners.model.FrameworkMethod;
     12 import org.junit.runners.model.InitializationError;
     13 import org.junit.runners.model.Statement;
     14 
     15 /**
     16  * A {@link BlockJUnit4ClassRunner} with parameters support. Parameters can be
     17  * injected via constructor or into annotated fields.
     18  */
     19 public class BlockJUnit4ClassRunnerWithParameters extends
     20         BlockJUnit4ClassRunner {
     21     private final Object[] parameters;
     22 
     23     private final String name;
     24 
     25     public BlockJUnit4ClassRunnerWithParameters(TestWithParameters test)
     26             throws InitializationError {
     27         super(test.getTestClass().getJavaClass());
     28         parameters = test.getParameters().toArray(
     29                 new Object[test.getParameters().size()]);
     30         name = test.getName();
     31     }
     32 
     33     @Override
     34     public Object createTest() throws Exception {
     35         if (fieldsAreAnnotated()) {
     36             return createTestUsingFieldInjection();
     37         } else {
     38             return createTestUsingConstructorInjection();
     39         }
     40     }
     41 
     42     private Object createTestUsingConstructorInjection() throws Exception {
     43         return getTestClass().getOnlyConstructor().newInstance(parameters);
     44     }
     45 
     46     private Object createTestUsingFieldInjection() throws Exception {
     47         List<FrameworkField> annotatedFieldsByParameter = getAnnotatedFieldsByParameter();
     48         if (annotatedFieldsByParameter.size() != parameters.length) {
     49             throw new Exception(
     50                     "Wrong number of parameters and @Parameter fields."
     51                             + " @Parameter fields counted: "
     52                             + annotatedFieldsByParameter.size()
     53                             + ", available parameters: " + parameters.length
     54                             + ".");
     55         }
     56         Object testClassInstance = getTestClass().getJavaClass().newInstance();
     57         for (FrameworkField each : annotatedFieldsByParameter) {
     58             Field field = each.getField();
     59             Parameter annotation = field.getAnnotation(Parameter.class);
     60             int index = annotation.value();
     61             try {
     62                 field.set(testClassInstance, parameters[index]);
     63             } catch (IllegalArgumentException iare) {
     64                 throw new Exception(getTestClass().getName()
     65                         + ": Trying to set " + field.getName()
     66                         + " with the value " + parameters[index]
     67                         + " that is not the right type ("
     68                         + parameters[index].getClass().getSimpleName()
     69                         + " instead of " + field.getType().getSimpleName()
     70                         + ").", iare);
     71             }
     72         }
     73         return testClassInstance;
     74     }
     75 
     76     @Override
     77     protected String getName() {
     78         return name;
     79     }
     80 
     81     @Override
     82     protected String testName(FrameworkMethod method) {
     83         return method.getName() + getName();
     84     }
     85 
     86     @Override
     87     protected void validateConstructor(List<Throwable> errors) {
     88         validateOnlyOneConstructor(errors);
     89         if (fieldsAreAnnotated()) {
     90             validateZeroArgConstructor(errors);
     91         }
     92     }
     93 
     94     @Override
     95     protected void validateFields(List<Throwable> errors) {
     96         super.validateFields(errors);
     97         if (fieldsAreAnnotated()) {
     98             List<FrameworkField> annotatedFieldsByParameter = getAnnotatedFieldsByParameter();
     99             int[] usedIndices = new int[annotatedFieldsByParameter.size()];
    100             for (FrameworkField each : annotatedFieldsByParameter) {
    101                 int index = each.getField().getAnnotation(Parameter.class)
    102                         .value();
    103                 if (index < 0 || index > annotatedFieldsByParameter.size() - 1) {
    104                     errors.add(new Exception("Invalid @Parameter value: "
    105                             + index + ". @Parameter fields counted: "
    106                             + annotatedFieldsByParameter.size()
    107                             + ". Please use an index between 0 and "
    108                             + (annotatedFieldsByParameter.size() - 1) + "."));
    109                 } else {
    110                     usedIndices[index]++;
    111                 }
    112             }
    113             for (int index = 0; index < usedIndices.length; index++) {
    114                 int numberOfUse = usedIndices[index];
    115                 if (numberOfUse == 0) {
    116                     errors.add(new Exception("@Parameter(" + index
    117                             + ") is never used."));
    118                 } else if (numberOfUse > 1) {
    119                     errors.add(new Exception("@Parameter(" + index
    120                             + ") is used more than once (" + numberOfUse + ")."));
    121                 }
    122             }
    123         }
    124     }
    125 
    126     @Override
    127     protected Statement classBlock(RunNotifier notifier) {
    128         return childrenInvoker(notifier);
    129     }
    130 
    131     @Override
    132     protected Annotation[] getRunnerAnnotations() {
    133         return new Annotation[0];
    134     }
    135 
    136     private List<FrameworkField> getAnnotatedFieldsByParameter() {
    137         return getTestClass().getAnnotatedFields(Parameter.class);
    138     }
    139 
    140     private boolean fieldsAreAnnotated() {
    141         return !getAnnotatedFieldsByParameter().isEmpty();
    142     }
    143 }
    144