6

考虑使用 JUnit 4 和 JUnitParams 的这个测试类:

import static junitparams.JUnitParamsRunner.$;
import junitparams.JUnitParamsRunner;
import junitparams.Parameters;

import org.junit.Test;
import org.junit.runner.RunWith;

@RunWith(JUnitParamsRunner.class)
public class JUnitParamsExample {

    private int[] getIntArray() {
        int array[] = new int[2];
        array[0] = 1;
        array[1] = 2;
        return array;
    }

    public Object getInts() {
        return $($(getIntArray()));
    }

    @Parameters(method = "getInts")
    @Test
    public void testIntArray(int... values) {
        //
    }

    private String[] getStringArray() {
        String array[] = new String[2];
        array[0] = "a";
        array[1] = "b";
        return array;
    }

    public Object getStrings() {
        return $($(getStringArray()));
    }

    @Parameters(method = "getStrings")
    @Test
    public void testStringArray(String... values) {
        //
    }
}

测试方法testIntArray运行良好,但testStringArray没有。错误输出为:

java.lang.IllegalArgumentException: Cannot parse parameters. Did you use , as column separator? a
    at junitparams.internal.InvokeParameterisedMethod.castParamsFromString(InvokeParameterisedMethod.java:51)
    at junitparams.internal.InvokeParameterisedMethod.<init>(InvokeParameterisedMethod.java:35)
    at junitparams.internal.ParameterisedTestClassRunner.buildMethodInvoker(ParameterisedTestClassRunner.java:121)
    at junitparams.internal.ParameterisedTestClassRunner.parameterisedMethodInvoker(ParameterisedTestClassRunner.java:115)
    at junitparams.JUnitParamsRunner.methodInvoker(JUnitParamsRunner.java:425)
    at org.junit.runners.BlockJUnit4ClassRunner.methodBlock(BlockJUnit4ClassRunner.java:251)
    at junitparams.JUnitParamsRunner.runChild(JUnitParamsRunner.java:405)
    at junitparams.JUnitParamsRunner.runChild(JUnitParamsRunner.java:383)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
Caused by: java.lang.IllegalArgumentException: Parameter type cannot be handled! Only primitive types and Strings can be used.
    at junitparams.internal.InvokeParameterisedMethod.castParameterDirectly(InvokeParameterisedMethod.java:171)
    at junitparams.internal.InvokeParameterisedMethod.castAllParametersToProperTypes(InvokeParameterisedMethod.java:122)
    at junitparams.internal.InvokeParameterisedMethod.castParamsUsingConverters(InvokeParameterisedMethod.java:101)
    at junitparams.internal.InvokeParameterisedMethod.castParamsFromString(InvokeParameterisedMethod.java:49)

我想知道为什么 int 数组有效而字符串数组无效。有没有办法使用 junitparams 将字符串数组传递给 varargs 测试方法?

编辑:我想写的是这样的:

public Object getStrings() {
        return $($("Hello", "world"),
                $("Me", "You"),
                $("Dog", "Cat"));
}

这样所有内部 $-entries 都被传递给 varargs 参数。

4

2 回答 2

5

好的,基本上它看起来像是 JUnitParams 中的一个错误。在下面的原始答案中应用修复后,当我们不希望它时,库仍然“解包” String[]- 考虑到源中正在进行的条件包装和解包的数量,似乎作者试图成为太聪明了,或者他们在任何时候都不知道自己在期待什么。不同之处在于safelyCastParamsToArray,在这种int[]情况下它传递了 anint[]并将其包装在 an 中Object[],而在这种String[]情况下,它传递了 a String[],它没有被包装,因为它已经可以转换为Object[]

可以通过使您的方法返回一个双重包装的数组来使其工作,如下所示:

return $((Object)$((Object)getStringArray()));

要不就:

return new Object[] { new Object[] { getStringArray() } };

但是,该int[]版本只需要单层包装,因此您可以使用:

return $(getIntArray());

而不是当前代码中的“被可变参数挫败的尝试双重包装”。

就我个人而言,我对这一切有些警惕——它有一种明显的“黑魔法,修补直到它起作用”的感觉,这种感觉在干净的 API 中并不存在......


原始答案

我认为问题在于String[]数组已经是一个Object[],所以你最终没有以你想要的方式包装它 - varargs 将参数视为整个数组而不是数组的一个元素。你可以很容易地解决这个问题:

public Object getStrings() {
    Object array = getStringArray();
    return $(array);
}

或者只是使用演员表:

public Object getStrings() {
    return $((Object) getStringArray());
}

或者在这种情况下忽略该$方法:

public Object getStrings() {
    return new Object[] { getStringArray() };
}

(我非常怀疑$($(...))任何一种情况下你都需要 - 你只是想创建一个数组数组,对吧?所以只需要一个级别的包装,无论如何你只会得到一个级别的包装,因为与您的原始代码不适用于字符串数组的原因完全相同。)

于 2014-02-05T16:24:44.387 回答
-1

也许zohhak图书馆可以帮助你。它基于junit参数。它允许您仅将注释中的参数作为字符串提供,但它允许您轻松地为这些字符串创建自己的自定义解析器

于 2014-03-04T01:35:26.593 回答