Reputation: 11
I have a Junit5 parameterised test method and I need to use my custom DataProvider class with methods that return Stream<Arguments> and are supposed to pass all their arguments to this test method altogether. The test method itself has the following signature:
public void testAllSteps(String section, String subsection, String rangeFilterName, String min, String max, String ListFilterName, List<String> values, int number)
and DataProvider contains the following methods:
public static Stream<String> sectionProvider() {
return Stream.of("Electronics", "Laptops");
}
public static Stream<String> rangeFilterProvider() {
return Stream.of("Price", "10000", "30000");
}
public static Stream<Arguments> listFilterProvider() {
return Stream.of(
Arguments.of("Manufacturer", List.of("HP, Lenovo")))
);
}
public static Stream<Arguments> conditionNumberProvider() {
return Stream.of(Arguments.of(12))
}
Thus sectionProvider() provides values for section and subsection parameters, and the other ones provide values for the other respective parameters. Such segregation is due to grouping the arguments into logic groups.
I know that I can state multiple methods in the @MethodSource annotation for parameterising the method, which I tried to do, like this:
@MethodSource({"utils.DataProvider#sectionProvider", "utils.DataProvider#rangeFilterProvider", "utils.DataProvider#listFilterProvider", "utils.DataProvider#conditionNumberProvider"})
but my program seems to fail to do that, saying the following:
org.junit.jupiter.api.extension.ParameterResolutionException: No ParameterResolver registered for parameter [java.lang.String arg1] in method [public void market.MarketTest.testAllSteps(java.lang.String,java.lang.String,java.lang.String,java.lang.String,java.lang.String,java.lang.String,java.util.List<java.lang.String>,int)].
I'm still kinda new to Junit5 parameterised testing, and I don't how pass all this data to my test method altogether.
I suspect I'll have to split my test method implementation into multiple methods (since it's presented in Allure steps) so I can provide a separate portion of arguments to each of them, and it will work, but according to the whole task I was given, it's not the right thing to do.
Maybe you have some ideas to share?
I tried to use a method that combines all Streams of Arguments into one but that also resulted into an error.
Also I tried to reduce the number of arguments in my test by grouping them into collections so it would be equal to the number of provider methods in the @MethodSource statement, but it made some code in other classes really clumsy, and I wasn't sure it could help, so I refused that idea before completing.
Upvotes: 1
Views: 340
Reputation: 20541
Here is a little snippet of test that combines 3 Arguments
into one.
public class AppTest {
@ParameterizedTest
@MethodSource("all")
public void test(String a, String b, String c) {
System.out.printf("a = %s b = %s c = %s%n", a, b, c);
}
public static Stream<Arguments> first() {
return Stream.of(
Arguments.arguments("f1"),
Arguments.arguments("f2"),
Arguments.arguments("f3")
);
}
public static Stream<Arguments> second() {
return Stream.of(
Arguments.arguments("s1"),
Arguments.arguments("s2"),
Arguments.arguments("s3")
);
}
public static Stream<Arguments> third() {
return Stream.of(
Arguments.arguments("t1"),
Arguments.arguments("t2"),
Arguments.arguments("t3")
);
}
public static Stream<Arguments> all() {
return zipArguments(first(), second(), third());
}
private static Stream<Arguments> zipArguments(Stream<Arguments> first, Stream<Arguments>... other) {
return Stream.of(other)
.reduce(first, AppTest::zipArguments);
}
private static Stream<Arguments> zipArguments(Stream<Arguments> first, Stream<Arguments> second) {
return zip(first, second, (f, s) ->
Arguments.of(Stream.concat(
Arrays.stream(f.get()),
Arrays.stream(s.get()))
.toArray(Object[]::new)));
}
public static <L, R, T> Stream<T> zip(Stream<L> leftStream, Stream<R> rightStream, BiFunction<L, R, T> combiner) {
Spliterator<L> lefts = leftStream.spliterator();
Spliterator<R> rights = rightStream.spliterator();
return StreamSupport.stream(new Spliterators.AbstractSpliterator<T>(Long.min(lefts.estimateSize(), rights.estimateSize()), lefts.characteristics() & rights.characteristics()) {
@Override
public boolean tryAdvance(Consumer<? super T> action) {
return lefts.tryAdvance(left -> rights.tryAdvance(right -> action.accept(combiner.apply(left, right))));
}
}, false);
}
}
Upvotes: 0
Reputation: 1132
May be reading this would help you: https://www.baeldung.com/parameterized-tests-junit-5
For example:
@MethodSource("utils.DataProvider#paramProvider")
public void testAllSteps(String section, String subsection, String rangeFilterName, String min, String max, String ListFilterName, List<String> values, int number)
then you can provide the params like this,
public static Stream<String> paramProvider() {
return Stream.of(
Arguments.of(
"Electronics",
"Laptops",
"Price",
"10000",
"30000",
"Manufacturer",
List.of("HP, Lenovo"),
12
)
);
}
Upvotes: -1