Home > Software engineering >  Rerunning parametrized JUnit test with string array parameter fails
Rerunning parametrized JUnit test with string array parameter fails

Time:03-21

While using enter image description here

fails with the following message:

java.lang.Exception: No tests found matching [{ExactMatcher:fDisplayName=test[1: A2 --> [Ljava.lang.String;@1e4a7dd4]], {ExactMatcher:fDisplayName=test[1: A2 --> Ljava.lang.String;@1e4a7dd4]] from org.junit.internal.requests.ClassRequest@6c3f5566

enter image description here

I'm pretty sure this is because JUnit doesn't 'like' my arrays; for some context: I'm using this to account for the fact that due to external circumstances, the code under test can produce one of two outcomes for a particular test case.

Here is some code to reproduce this:

package com.stackexchange.toolbox;

import java.util.ArrayList;
import java.util.Arrays;

import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;

@RunWith(Parameterized.class)
public class Tester {
    public Tester(String source, Object target) {
        this.source = source;
        this.target = target;
    }

    private final String source;
    private final Object target;

    private static final Object[][] testCases = { { "A1", "B1" }, { "A2", new String[] { "B2", "C2" } } };

    @Parameters(name = "{index}: {0} --> {1}")
    public static Iterable<Object[]> data() throws Exception {
        return new ArrayList<>(Arrays.asList(testCases));
    }

    @Test
    public void test() throws Exception {
        if (target instanceof String) {
            Assert.assertEquals(source.charAt(1), ((String)target).charAt(1));
        } else {
            for (String target : (String[])this.target) {
                Assert.assertEquals(source.charAt(1), target.charAt(1));
            }
        }
    }
}

Is there an easy way to fix this, perhaps with Lists or variadic arguments? Most of the (100 ) test cases are simple 'source', 'target' entries, and I'd like to keep the conciseness of { "A1", "B1" }.

CodePudding user response:

This seems to be a limitation of JUnit4 (at least you get the same error on the command line).

The simplest and straightforward solution would be to migrate from JUnit4 to JUnit5, which would also mean less code:

package com.stackexchange.toolbox;

import java.util.Arrays;
import java.util.stream.Stream;

import org.junit.Assert;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;

class Tester {
    
    private static final Object[][] testCases = { { "A1", "B1" }, { "A2", new String[] { "B2", "C2" } } };

    @ParameterizedTest(name = "{index}: {0} --> {1}")
    @MethodSource("provideArguments")
    void test(String source, Object target) {
        if (target instanceof String) {
            Assert.assertEquals(source.charAt(1), ((String)target).charAt(1));
        } else {
            for (String targetElement : (String[])target) {
                Assert.assertEquals(source.charAt(1), targetElement.charAt(1));
            }
        }
    }

    static Stream<? extends Arguments> provideArguments() throws Exception {
        return Arrays.stream(testCases).map(Arguments::of);
    }

}
  • Related