Issue
While using parametrized JUnit tests in Eclipse, I'm running into a problem when I want to rerun a single test. The tests themselves run fine, and while I can rerun the first test from the context menu, rerunning the second test:
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
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 List
s 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" }
.
Solution
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);
}
}
Answered By - howlger
Answer Checked By - Timothy Miller (JavaFixing Admin)