• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
BlockJUnit4ClassRunnerWithParameters(TestWithParameters test)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
createTest()34     public Object createTest() throws Exception {
35         if (fieldsAreAnnotated()) {
36             return createTestUsingFieldInjection();
37         } else {
38             return createTestUsingConstructorInjection();
39         }
40     }
41 
createTestUsingConstructorInjection()42     private Object createTestUsingConstructorInjection() throws Exception {
43         return getTestClass().getOnlyConstructor().newInstance(parameters);
44     }
45 
createTestUsingFieldInjection()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
getName()77     protected String getName() {
78         return name;
79     }
80 
81     @Override
testName(FrameworkMethod method)82     protected String testName(FrameworkMethod method) {
83         return method.getName() + getName();
84     }
85 
86     @Override
validateConstructor(List<Throwable> errors)87     protected void validateConstructor(List<Throwable> errors) {
88         validateOnlyOneConstructor(errors);
89         if (fieldsAreAnnotated()) {
90             validateZeroArgConstructor(errors);
91         }
92     }
93 
94     @Override
validateFields(List<Throwable> errors)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
classBlock(RunNotifier notifier)127     protected Statement classBlock(RunNotifier notifier) {
128         return childrenInvoker(notifier);
129     }
130 
131     @Override
getRunnerAnnotations()132     protected Annotation[] getRunnerAnnotations() {
133         return new Annotation[0];
134     }
135 
getAnnotatedFieldsByParameter()136     private List<FrameworkField> getAnnotatedFieldsByParameter() {
137         return getTestClass().getAnnotatedFields(Parameter.class);
138     }
139 
fieldsAreAnnotated()140     private boolean fieldsAreAnnotated() {
141         return !getAnnotatedFieldsByParameter().isEmpty();
142     }
143 }
144