Java – how do I use a JUnit parameterized runner with a varargs constructor?
I wrote a model example to illustrate this without divulging any confidential information This is a "virtual" example that does nothing, but the problem occurs in the test initializer
@RunWith(Parameterized.class) public class ExampleParamTest { int ordinal; List<String> strings; public ExampleParamTest(int ordinal,String... strings) { this.ordinal = ordinal; if (strings.length == 0) { this.strings = null; } else { this.strings = Arrays.asList(strings); } } @Parameters public static Collection<Object[]> data() { return Arrays.asList(new Object[][] { {0,"hello","goodbye"},{1,"farewell"} }); } @Test public void dotest() { Assert.assertTrue(true); } }
Basically, I have a test constructor that accepts multiple parameters of a local list variable, and I want to populate it with an array initializer The test method will handle local list variables correctly – I have removed this logic to simplify the test
When I wrote this article, my ide had no complaints about syntax and test class construction, and there were no compilation errors But when I run it, I get:
doTest[0]: java.lang.IllegalArgumentException: wrong number of arguments at java.lang.reflect.Constructor.newInstance(UnkNown Source) doTest[1]: java.lang.IllegalArgumentException: argument type mismatch at java.lang.reflect.Constructor.newInstance(UnkNown Source)
What's wrong here and how can I use this model correctly?
Solution
I can't test it now, but I think if you call a method or constructor with variable parameters, you must use an array instead of a list of variable values to call it
If I'm right, then this should work:
@Parameters public static Collection<Object[]> data() { return Arrays.asList(new Object[][] { {0,new String[]{"hello","goodbye"}},new String[]{"farewell"}} }); }
Some explanation
At the source level, we can write
test = ExampleParamTest(0,"one","two");
The compiler converts it to a string array JUnit uses reflection and call APIs. From this point of view, constructor signatures are
public ExampleParamTest(int i,String[] strings);
Therefore, to call the constructor - which is what JUnit does internally - you must pass an integer and a string array