Short answer
there's no way to parametrize class creation with JUnit 5 following the style of JUnit 4.
Fortunately, the very intention of separation test logic and test input data (parameters) can be implemented differently.
JUnit 5 has its own approach for making parameterized tests, and, of course, it is different from JUnit 4. The new approach does not allow to use parameterized fixtures at the class level, i.e. through its every test method.
So every parameterized test method should be explicitly annotated with a link to parameters.
JUnit 5 provides a plenty of parameter source types, that could be found in documentation and guides
In your case, the simplest way to migrate from @Parameters
of Junit 4 is using @MethodSource
or @ArgumentsSource
of org.junit.jupiter.params.provider.*
.
JUnit 4:
@RunWith(Parameterized.class)
public class MyTestWithJunit4 {
@Parameters
public static Collection<Object[]> data() {
return Arrays.asList(new Object[][] {
{ 0, 0, 0 },
{ 1, 2, 3 },
{ 5, 3, 8 }
});
}
int first;
int second;
int sum;
public MyTestWithJunit4(int first, int second, int sum) {
this.first = first;
this.second = second;
this.sum = sum;
}
@Test
public void test() {
assertEquals(sum, first + second));
}
}
JUnit 5 (with @MethodSource
):
class MyTestWithJunit5 {
@DisplayName("Test with @MethodSource")
@ParameterizedTest(name = "{index}: ({0} + {1}) => {2})")
@MethodSource("localParameters")
void test(int first, int second, int sum) {
assertEquals(sum, first + second);
}
static Stream<Arguments> localParameters() {
return Stream.of(
Arguments.of(0, 0, 0),
Arguments.of(1, 2, 3),
Arguments.of(5, 3, 8)
);
}
}
JUnit 5 (with @ArgumentsSource
):
class MyTestWithJunit5 {
@DisplayName("Test with @ArgumentsSource")
@ParameterizedTest(name = "{index}: ({0} + {1}) => {2})")
@ArgumentsSource(Params.class)
void test(int first, int second, int sum) {
assertEquals(sum, first + second);
}
static class Params implements ArgumentsProvider {
@Override
public Stream<? extends Arguments> provideArguments(ExtensionContext context) {
return Stream.of(
Arguments.of(0, 0, 0),
Arguments.of(1, 2, 3),
Arguments.of(5, 3, 8)
);
}
}
}
Consider that a method in @MethodSource
and a class in @ArgumentsSource
could be described anywhere, not only inside the same class where the test methods are located. Also @MethodSource
allows to provide multiple source methods, since its value
is a String[]
.
Some remarks and comparison
In JUnit 4 we could only have a single factory method providing parameters, and the tests were supposed to be built around those parameters.
On the contrary, JUnit 5 gives more abstraction and flexibility in binding parameters and decouples test logic from its parameters, which are secondary.
That allows building tests independently from parameter sources, and easily change them when needed.
Dependency requirement
Parameterized tests feature is not included in the core junit-jupiter-engine
,
but is located in a separate dependency junit-jupiter-params
.