Search code examples
javaunit-testingjunitparameterizeddata-driven-tests

JUnit test - Wrong number of parameters and @Parameter fields


I have no experience with JUnit tests, but I am trying to learn them. For start, I wrote a very simple class UrlParams, which contains two public methods - void addParameter(String name, String value) and String buildUrl(). The usage of my class is also very simple.

UrlParams urlParams = new UrlParams("http://baseurl.com");
urlParams.addParameter("name1", "value1");
urlParams.addParameter("name2", "value2");
String url = urlParams.buildUrl();
System.out.println(url);

The output from this code is http://baseurl.com?name1=value1&name2=value2.

Now, I am trying to write test class. I would like to test my class with different count of parameters, so I decided to use parameterized test. I wrote following code:

@RunWith(Parameterized.class)
public class UrlParamsTest {

    @Parameterized.Parameter(value = 0)
    public UrlParameter[] paramsList;


    @Parameterized.Parameters
    public static Collection<Object[]> data() {
        List<Object[]> data = new LinkedList<Object[]>();

        // Test 1
        UrlParameter[] parameterList1 = new UrlParameter[3];
        parameterList1[0] = new UrlParameter("name1", "value1");
        parameterList1[1] = new UrlParameter("name2", "value2");
        parameterList1[2] = new UrlParameter("name3", "value3");

        // Test 2
        UrlParameter[] parameterList2 = new UrlParameter[2];
        parameterList2[0] = new UrlParameter("name1", "value1");
        parameterList2[1] = new UrlParameter("name2", "value2");

        // Test 3
        UrlParameter[] parameterList3 = new UrlParameter[0];

        data.add(parameterList1);
        data.add(parameterList2);
        data.add(parameterList3);
        return data;
    }

    @Test
    public void buildUrlTest() {
        final String baseUrl = "http://baseurl.com";
        UrlParams urlParams = new UrlParams(baseUrl);

        String expected = baseUrl;
        if (paramsList.length > 0) {
            expected += "?";
        }

        int index = 0;
        for (UrlParameter p : paramsList) {
            urlParams.addParameter(p.name, p.value);
            expected += p.name + "=" + p.value;
            if (index != paramsList.length - 1) {
                expected += "&";
            }
        }
        String buildUrl = urlParams.buildUrl();

        assertEquals(expected, buildUrl);
        System.out.println("Expected = " + expected + " Created = " + buildUrl);
    }


    static class UrlParameter {
        String name, value;

        public UrlParameter(String name, String value) {
            this.name = name;
            this.value = value;
        }
    }
}

If I am trying to run this test, I see the exceptions below.

java.lang.Exception: Wrong number of parameters and @Parameter fields. @Parameter fields counted: 1, available parameters: 3.
java.lang.Exception: Wrong number of parameters and @Parameter fields. @Parameter fields counted: 1, available parameters: 2.
java.lang.Exception: Wrong number of parameters and @Parameter fields. @Parameter fields counted: 1, available parameters: 0.

I am new in JUnit tests and I have no idea what is wrong. Could you tell me please, what I am doing wrong? Thank you.


Solution

  • Each entry in the List<Object[]> data is a set of parameters for your data-driven unit tests. JUnit will take each of them and run the parametrized tests. Because you define only one parameter for tests, JUnit expects each of the Object[] entry to have a length equal to 1.

    You are defining the params as (pseudocode):

    [
        [param1, param2, param3]
        [param1, param2]
        []
    ]
    

    So, basically, you tell JUnit to run your first case with three arguments, the second with two and the last one with no arguments at all. It is no possible.

    What you want is to run each test case with exactly one argument, that is always an array of your parameters:

    [
        [[param1, param2, param3]]
        [[param1, param2]]
        [[]]
    ]
    

    In order to achieve that, you need to change

    data.add(parameterList1);
    data.add(parameterList2);
    data.add(parameterList3);
    

    to

    data.add(new Object[] { parameterList1 });
    data.add(new Object[] { parameterList2 });
    data.add(new Object[] { parameterList3 });