2

我有使用 TestNG 的单元测试,我尝试迁移到 JUnit Jupiter (JUnit 5),我想知道哪种方法最好:

测试NG

@DataProvider
public Object[][] invalidPortNumbers() {
    return new Object[][] {
            { "--http", "" },
            { "--http", "-42" },
            { "--http", "0" },
            { "--http", "not_a_port_number" },
            { "--https", "67000" }
    };
}

@Test(dataProvider = "invalidPortNumbers",
      expectedExceptions = ParameterException.class,
      expectedExceptionsMessageRegExp = ".* is not valid port number .*")
public void shouldFailToValidatePortNumber(final String... args) {
    new CommandLineParser(args);
}

我看到转移到JUnit Jupiter,我可以这样做:

static Stream<Arguments> invalidPortNumbers2() {
    return Stream.of(
            Arguments.of((Object) new String[] { "--http", "-42" }),
            Arguments.of((Object) new String[] { "--http", "0" }),
            Arguments.of((Object) new String[] { "--http", "not_a_port_number" }),
            Arguments.of((Object) new String[] { "--https", "67000" })
    );
}

@ParameterizedTest
@MethodSource("invalidPortNumbers2")
void shouldFailToValidatePortNumber(final String... args) {
    assertThatThrownBy(() -> new CommandLineParser(args))
            .isInstanceOf(ParameterException.class)
            .hasMessageMatching(".* is not valid port number .*");
}

有没有其他方法可以简化这一点并保留以前的 dataProvider 结构以最小化更改?

谢谢。

4

1 回答 1

2

对于 JUnit Jupiter 中的参数化测试,如果通过引用的方法的返回类型@MethodSource是二维数组,则内部数组的值将作为多个参数传递给单个测试方法调用。这意味着没有直接的方法可以将接受 var-args(或显式数组)的测试方法从 TestNG@DataProvider迁移到 JUnit Jupiter @MethodSource

invalidPortNumbers2()是解决此限制的合适解决方法,但您可能更喜欢其他解决方法。


更新答案:

将所有参数作为单个数组处理的最简单方法是通过ArgumentsAccessorAPI。

如果您创建现有invalidPortNumbers()方法static,则可以“按原样”使用它并将参数转换为数组,如下所示。

@ParameterizedTest
@MethodSource("invalidPortNumbers")
void shouldFailToValidatePortNumber(ArgumentsAccessor accessor) {
    Object[] args = accessor.toArray();
    // Use args ...
}

不过,在 JUnit Jupiter 中,您可能会发现@CsvSource在此类用例中使用优于@MethodSource使用 。因此,为了达到相同的目标,您可以按如下方式重写您的测试并摆脱该invalidPortNumbers()方法。

@ParameterizedTest
@CsvSource({
    "--http, ''",
    "--http, -42",
    "--http, 0",
    "--http, not_a_port_number",
    "--https, 67000"
})
void shouldFailToValidatePortNumber(ArgumentsAccessor accessor) {
    Object[] args = accessor.toArray();
    // Use args ...
}

原答案:

对于初学者,以下实用方法将有助于简化事情(在名为的类中声明,VarArgsParamsTests但可以移至通用实用程序类)。请注意,它arguments()是通过静态导入的org.junit.jupiter.params.provider.Arguments.arguments

static Arguments arrayArguments(String... array) {
    return arguments((Object) array);
}

鉴于此,如果您想invalidPortNumbers()尽可能少地修改现有方法,您可以将其签名重新定义为static String[][] invalidPortNumbers()并引入您实际引用的以下方法@MethodSource

static Stream<Arguments> invalidPortNumbersArguments() {
    return Arrays.stream(invalidPortNumbers()).map(VarArgsParamsTests::arrayArguments);
}

如果您愿意invalidPortNumbers()更多地修改现有方法,则可以将其更改为以下也使用arrayArguments()实用程序方法的方法。

static Stream<Arguments> invalidPortNumbers() {
    return Stream.of(
        arrayArguments("--http", ""),
        arrayArguments("--http", "-42"),
        arrayArguments( "--http", "0"),
        arrayArguments( "--http", "not_a_port_number"),
        arrayArguments( "--https", "67000")
    );
}
于 2020-11-16T10:42:38.870 回答