使用字符串数组参数运行参数化 JUnit 测试失败

Rerunning parametrized JUnit test with string array parameter fails

在 Eclipse 中使用 parametrized JUnit tests 时,我 运行 在想重新 运行 单个测试时遇到了问题。测试本身 运行 很好,而我 可以 从上下文菜单重新 运行 第一个测试,重新 运行 第二个测试:

失败并显示以下消息:

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

我很确定这是因为 JUnit 没有 'like' 我的数组;对于某些上下文:我用它来解释由于外部环境,被测代码可以为特定测试用例产生两种结果之一的事实。

下面是一些重现此代码的代码:

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));
            }
        }
    }
}

有没有一种简单的方法可以解决这个问题,也许使用 Lists 或可变参数?大多数(100+)测试用例都是简单的'source'、'target'条目,我想保持{ "A1", "B1" }.

的简洁

这似乎是 JUnit4 的限制 (at least you get the same error on the command line)。

最简单直接的解决方案是从 JUnit4迁移到 JUnit5,这也意味着更少的代码:

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);
    }

}