#testng #junit5 #testng-dataprovider #junit-jupiter
#testng #junit5 #testng-dataprovider #junit-jupiter
Вопрос:
У меня есть модульные тесты с использованием 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, чтобы минимизировать изменения?
Спасибо.
Комментарии:
1. Что произойдет, если вы создадите свой существующий
invalidPortNumbers()
методstatic
и ссылаетесь на него@MethodSource
?2. Я получил следующее исключение:
org.junit.jupiter.api.extension.ParameterResolutionException: Error converting parameter at index 0: No implicit conversion to convert object of type java.lang.String to type [Ljava.lang.String;
Ответ №1:
При параметризованных тестах в JUnit Jupiter, если возвращаемый тип метода, на который ссылается via @MethodSource
, представляет собой двумерный массив, значения внутренних массивов будут переданы в качестве нескольких аргументов при вызове одного метода тестирования. Это означает, что нет простого способа перенести метод тестирования, который принимает переменные аргументы (или явный массив) из 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 вы можете обнаружить, что использование a @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")
);
}
Комментарии:
1. Пожалуйста, обратите внимание, что я добавил решения, используя API ArgumentsAccessor.