-
Notifications
You must be signed in to change notification settings - Fork 3.3k
Description
(This is primarily a note for me to fix this shortly, since I've come up against it in #639)
This fails, saying no valid parameters were found:
@RunWith(Theories.class)
public static class SingleDataPointTheory {
@DataPoint
public static Object num() {
return 10;
}
@Theory
public void theory(Integer x) {
}
}
This meanwhile, happily passes, using the parameter from the array:
@RunWith(Theories.class)
public static class DataPointArrayTheory {
@DataPoints
public static Object[] num() {
return new Object[] { 10 };
}
@Theory
public void theory(Integer x) {
}
}
In addition, this doesn't pass (while the single @DataPoint
equivalent does), as it finds no parameters:
@RunWith(Theories.class)
public static class DataPointArrayTheoryWithPrimitives {
@DataPoints
public static int[] num() {
return new int[] { 10 };
}
@Theory
public void theory(int x) {
}
}
This is because of two closely related problems:
- AllMembersSupplier chooses which values to use for parameters in slightly different ways depending on where the parameter came from. For all fields and single-valued DataPoint methods, it's based on the static type information available (the method return type/field type). For multi-valued DataPoints methods, it's based on the actual type of the value in the DataPoints array (note that this differs both from the single-valued version, and the multi-valued field array version), as tested by ParameterSignature.canAcceptValue()
- The values examined in canAcceptValue are boxed first, and ParameterSignature.canAcceptValue doesn't take into account boxing. Thus canAcceptValue(Integer) fails for int method parameters, meaning int's found in DataPoints arrays returned by these methods are never considered as potential parameters. In addition, canAcceptValue(int) will fail for Integer method parameters, but since the values are always autoboxed first this never comes up.
I'd suggest that either all fields and methods are based purely on whether the static type is assignable (e.g. Object fields are never used for Integer parameters, even if the values are Integers), or that parameters are always considered on their value (i.e. field type is irrelevant, as long as the values can be used for the given parameter).
I think the second is more intuitive myself; any datapoint that can be legitimately used for a parameter should be. Also because I've got another nearly finished implementation for Iterable datapoints that requires that behaviour, as you can't get the type of an Iterable directly, unlike with String[], so you have to always examine these values.