Skip to content

Commit b4b1b31

Browse files
author
David Saff
committed
Merge pull request #658 from pimterry/iterable-datapoints
Added support for iterable datapoints
2 parents 540fa75 + b4b2070 commit b4b1b31

File tree

3 files changed

+98
-10
lines changed

3 files changed

+98
-10
lines changed

Diff for: src/main/java/org/junit/experimental/theories/DataPoints.java

+13-4
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,9 @@
88
import java.lang.annotation.Target;
99

1010
/**
11-
* Annotating an array-typed field or method with @DataPoints will cause
12-
* the values in the array (or returned array) to be used as potential
13-
* parameters for theories in that class, when run with the
11+
* Annotating an array or iterable-typed field or method with @DataPoints
12+
* will cause the values in the array or iterable given to be used as potential
13+
* parameters for theories in that class when run with the
1414
* {@link org.junit.experimental.theories.Theories Theories} runner.
1515
* <p>
1616
* DataPoints will only be considered as potential values for parameters for
@@ -27,6 +27,14 @@
2727
* &#064;ParameterSuppliedBy} annotations) will use all DataPoints that are
2828
* assignable to the parameter type as potential values, including named sets of
2929
* DataPoints.
30+
* <p>
31+
* DataPoints methods whose array types aren't assignable from the target
32+
* parameter type (and so can't possibly return relevant values) will not be
33+
* called when generating values for that parameter. Iterable-typed datapoints
34+
* methods must always be called though, as this information is not available
35+
* here after generic type erasure, so expensive methods returning iterable
36+
* datapoints are a bad idea.
37+
*
3038
* <pre>
3139
* &#064;DataPoints
3240
* public static String[] dataPoints = new String[] { ... };
@@ -48,8 +56,9 @@
4856
* @see org.junit.experimental.theories.FromDataPoints
4957
*/
5058
@Retention(RetentionPolicy.RUNTIME)
51-
@Target({FIELD, METHOD})
59+
@Target({ FIELD, METHOD })
5260
public @interface DataPoints {
5361
String[] value() default {};
62+
5463
Class<? extends Throwable>[] ignoredExceptions() default {};
5564
}

Diff for: src/main/java/org/junit/experimental/theories/internal/AllMembersSupplier.java

+30-4
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import java.lang.reflect.Field;
55
import java.util.ArrayList;
66
import java.util.Collection;
7+
import java.util.Iterator;
78
import java.util.List;
89

910
import org.junit.Assume;
@@ -76,9 +77,11 @@ private void addMultiPointMethods(ParameterSignature sig, List<PotentialAssignme
7677
for (FrameworkMethod dataPointsMethod : getDataPointsMethods(sig)) {
7778
Class<?> returnType = dataPointsMethod.getReturnType();
7879

79-
if (returnType.isArray() && sig.canPotentiallyAcceptType(returnType.getComponentType())) {
80+
if ((returnType.isArray() && sig.canPotentiallyAcceptType(returnType.getComponentType())) ||
81+
Iterable.class.isAssignableFrom(returnType)) {
8082
try {
81-
addArrayValues(sig, dataPointsMethod.getName(), list, dataPointsMethod.invokeExplosively(null));
83+
addDataPointsValues(returnType, sig, dataPointsMethod.getName(), list,
84+
dataPointsMethod.invokeExplosively(null));
8285
} catch (Throwable throwable) {
8386
DataPoints annotation = dataPointsMethod.getAnnotation(DataPoints.class);
8487
if (annotation != null && isAssignableToAnyOf(annotation.ignoredExceptions(), throwable)) {
@@ -101,9 +104,10 @@ private void addSinglePointMethods(ParameterSignature sig, List<PotentialAssignm
101104

102105
private void addMultiPointFields(ParameterSignature sig, List<PotentialAssignment> list) {
103106
for (final Field field : getDataPointsFields(sig)) {
104-
addArrayValues(sig, field.getName(), list, getStaticFieldValue(field));
107+
Class<?> type = field.getType();
108+
addDataPointsValues(type, sig, field.getName(), list, getStaticFieldValue(field));
105109
}
106-
}
110+
}
107111

108112
private void addSinglePointFields(ParameterSignature sig, List<PotentialAssignment> list) {
109113
for (final Field field : getSingleDataPointFields(sig)) {
@@ -114,6 +118,16 @@ private void addSinglePointFields(ParameterSignature sig, List<PotentialAssignme
114118
}
115119
}
116120
}
121+
122+
private void addDataPointsValues(Class<?> type, ParameterSignature sig, String name,
123+
List<PotentialAssignment> list, Object value) {
124+
if (type.isArray()) {
125+
addArrayValues(sig, name, list, value);
126+
}
127+
else if (Iterable.class.isAssignableFrom(type)) {
128+
addIterableValues(sig, name, list, (Iterable<?>) value);
129+
}
130+
}
117131

118132
private void addArrayValues(ParameterSignature sig, String name, List<PotentialAssignment> list, Object array) {
119133
for (int i = 0; i < Array.getLength(array); i++) {
@@ -123,6 +137,18 @@ private void addArrayValues(ParameterSignature sig, String name, List<PotentialA
123137
}
124138
}
125139
}
140+
141+
private void addIterableValues(ParameterSignature sig, String name, List<PotentialAssignment> list, Iterable<?> iterable) {
142+
Iterator<?> iterator = iterable.iterator();
143+
int i = 0;
144+
while (iterator.hasNext()) {
145+
Object value = iterator.next();
146+
if (sig.canAcceptValue(value)) {
147+
list.add(PotentialAssignment.forValue(name + "[" + i + "]", value));
148+
}
149+
i += 1;
150+
}
151+
}
126152

127153
private Object getStaticFieldValue(final Field field) {
128154
try {

Diff for: src/test/java/org/junit/tests/experimental/theories/internal/AllMembersSupplierTest.java

+55-2
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import static org.junit.Assert.assertThat;
77
import static org.junit.tests.experimental.theories.TheoryTestUtils.potentialAssignments;
88

9+
import java.util.Arrays;
910
import java.util.List;
1011

1112
import org.junit.Rule;
@@ -23,7 +24,6 @@ public class AllMembersSupplierTest {
2324
@Rule
2425
public ExpectedException expected = ExpectedException.none();
2526

26-
2727
public static class HasDataPointsArrayField {
2828
@DataPoints
2929
public static String[] list = new String[] { "qwe", "asd" };
@@ -153,4 +153,57 @@ private List<PotentialAssignment> allMemberValuesFor(Class<?> testClass,
153153
testClass.getConstructor(constructorParameterTypes))
154154
.get(0));
155155
}
156-
}
156+
157+
public static class HasDataPointsListField {
158+
@DataPoints
159+
public static List<String> list = Arrays.asList("one", "two");
160+
161+
@Theory
162+
public void theory(String param) {
163+
}
164+
}
165+
166+
@Test
167+
public void dataPointsCollectionFieldsShouldBeRecognized() throws Throwable {
168+
List<PotentialAssignment> assignments = potentialAssignments(
169+
HasDataPointsListField.class.getMethod("theory", String.class));
170+
171+
assertEquals(2, assignments.size());
172+
}
173+
174+
public static class HasDataPointsListMethod {
175+
@DataPoints
176+
public static List<String> getList() {
177+
return Arrays.asList("one", "two");
178+
}
179+
180+
@Theory
181+
public void theory(String param) {
182+
}
183+
}
184+
185+
@Test
186+
public void dataPointsCollectionMethodShouldBeRecognized() throws Throwable {
187+
List<PotentialAssignment> assignments = potentialAssignments(
188+
HasDataPointsListMethod.class.getMethod("theory", String.class));
189+
190+
assertEquals(2, assignments.size());
191+
}
192+
193+
public static class HasDataPointsListFieldWithOverlyGenericTypes {
194+
@DataPoints
195+
public static List<Object> list = Arrays.asList("string", new Object());
196+
197+
@Theory
198+
public void theory(String param) {
199+
}
200+
}
201+
202+
@Test
203+
public void dataPointsCollectionShouldBeRecognizedIgnoringStrangeTypes() throws Throwable {
204+
List<PotentialAssignment> assignments = potentialAssignments(
205+
HasDataPointsListFieldWithOverlyGenericTypes.class.getMethod("theory", String.class));
206+
207+
assertEquals(1, assignments.size());
208+
}
209+
}

0 commit comments

Comments
 (0)