I have a problem with single/multiple arrays as varargs
parameters used in JUnit5
MethodSource
's Arguments
.
If multiple arrays (empty or not) are passed, everything's fine, but if only a single array is passed, the Arguments.of()
varargsunwraps the array and the originally intended as-array source is destroyed, which is not what I want. The problem relates to any varargs
method parameters, not just to Arguments
.
Method Arguments source:
static Object[] objectsWithNull = new Object[] { null }; // -> [null] intended array test argument
public static final List<Arguments> objSource() {
return List.of(
Arguments.of(objectsWithNull) // varargsArguments.of(Object...) unwraps array, not desired -> null
);
}
public static final List<Arguments> objSources() {
return List.of(
Arguments.of(objectsWithNull, objectsWithNull) // -> [null], [null] OK
);
}
Test method utilizing MethodSource
arguments in 'TestClasses':
@ParameterizedTest
@MethodSource("objSource")
public <T> void myTest(final T t2) {
assertDoesNotThrow(() -> { // test code
});
}
@ParameterizedTest
@MethodSource("objSources")
public <T> void myTest(final T t1, final T t2) {
assertDoesNotThrow(() -> { // test code
});
}
Actually desired: -> [null] as in objSources
Arguments.of(objectsWithNull,objectsWithNull); // -> [null], [null] OK
Even worse, while for multiple empty arrays there's no problem:
Object[] objectsEmpty = new Object[0];
Arguments.of(objectsEmpty,objectsEmpty); // -> [], [] OK
A single empty array will throw org.junit.jupiter.api.extension.ParameterResolutionException: No ParameterResolver registered for parameter [T arg0] in method ... [public void ... TestClasses.myTest(T,T)]:
Arguments.of(objectsEmpty); // -> throws
Even more confusing, while using a typed null Object reference works, using a plain null value or a typed null array reference will throw an Exception:
static Object nullObjRef = (Object) null;
static Object[] nullArrayRef = (Object[]) null;
public static final List<Arguments> objSource() {
return List.of(
Arguments.of(nullObjRef), // #A -> OK
Arguments.of(nullArrayRef), // #B -> throws org.junit.platform.commons.PreconditionViolationException: argument array must not be null
Arguments.of(null) // #C -> throws org.junit.platform.commons.PreconditionViolationException: argument array must not be null
);
}
While passing a null array reference causing an internal NPE
in #B might be understandable, #A vs. #C (typed null
reference vs. plain null
) is not quite.
Also, a single empty array throwing a ParameterResolutionException
seems rather random to me (while probably just a caught internal NPE
or ArrayIndexOutOfBoundsException
), instead of just passing through the empty array.
Finally, I'd like to know, if there's an easy, clean way of avoiding the unwrapping effect of single array arguments by varargs
, as described in the first example, without the inconvenience of double-wrapping and unwrapping single or multiple arrays from inside a container object, which is passed to Arguments.of()
.
EDIT:
When testing this, I've also found, that passing an array into a varargs
parameter, the result is an array-wrapped array. Didn't cross such issues before trying to pass on arrays as test values per JUnit
Arguments
and MethodSource
, though. Maybe reading this first would've helped:
Passing arrays with varargs
Anyway, these effects make using Arguments
in conjunction with arrays more difficult.