如何将 TestNG @DataProvider 迁移到 JUnit Jupiter @ParameterizedTest
How to migrate TestNG @DataProvider to JUnit Jupiter @ParameterizedTest
我使用 TestNG 进行了单元测试,我尝试将其迁移到 JUnit Jupiter (JUnit 5),我想知道哪种方法最好:
TestNG:
@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 结构以尽量减少更改?
谢谢。
对于 JUnit Jupiter 中的参数化测试,如果通过 @MethodSource
引用的方法的 return 类型是二维数组,则内部数组的值将作为多个参数传递给单个测试方法调用。这意味着没有直接的方法可以将接受可变参数(或显式数组)的测试方法从 TestNG 的 @DataProvider
迁移到 JUnit Jupiter 的 @MethodSource
.
您的 invalidPortNumbers2()
是解决此限制的合适解决方法,但您可能更喜欢其他解决方法。
更新答案:
将所有参数作为单个数组处理的最简单方法是通过 ArgumentsAccessor
API.
如果您创建现有的 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
的 class 中声明,但可以移至通用实用程序 class)。请注意,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")
);
}
我使用 TestNG 进行了单元测试,我尝试将其迁移到 JUnit Jupiter (JUnit 5),我想知道哪种方法最好:
TestNG:
@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 结构以尽量减少更改?
谢谢。
对于 JUnit Jupiter 中的参数化测试,如果通过 @MethodSource
引用的方法的 return 类型是二维数组,则内部数组的值将作为多个参数传递给单个测试方法调用。这意味着没有直接的方法可以将接受可变参数(或显式数组)的测试方法从 TestNG 的 @DataProvider
迁移到 JUnit Jupiter 的 @MethodSource
.
您的 invalidPortNumbers2()
是解决此限制的合适解决方法,但您可能更喜欢其他解决方法。
更新答案:
将所有参数作为单个数组处理的最简单方法是通过 ArgumentsAccessor
API.
如果您创建现有的 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
的 class 中声明,但可以移至通用实用程序 class)。请注意,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")
);
}