Automate a parameterized test using a custom argument provider in JUnit
Preconditions (2)
✅ Expected Result: The parameterized test runs successfully for each data set provided by the custom argument provider, passing all assertions.
import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.ArgumentsProvider; import org.junit.jupiter.params.provider.ArgumentsSource; import java.util.stream.Stream; import static org.junit.jupiter.api.Assertions.assertTrue; public class CustomArgumentProviderTest { static class MyCustomArgumentProvider implements ArgumentsProvider { @Override public Stream<? extends Arguments> provideArguments(ExtensionContext context) { return Stream.of( Arguments.of("apple", 5), Arguments.of("banana", 6), Arguments.of("cherry", 6) ); } } @ParameterizedTest(name = "Test with fruit={0} and length={1}") @ArgumentsSource(MyCustomArgumentProvider.class) void testWithCustomArguments(String fruit, int length) { assertTrue(fruit.length() == length, "Fruit length should match the provided length"); } }
This test class defines a MyCustomArgumentProvider that implements ArgumentsProvider. It overrides provideArguments to return a stream of Arguments objects, each containing a fruit name and its length.
The test method testWithCustomArguments is annotated with @ParameterizedTest and @ArgumentsSource to use the custom provider. It receives the parameters and asserts the fruit's length matches the expected length.
This setup keeps test data separate from the test logic, making tests cleaner and reusable.
Now add data-driven testing with 3 different sets of fruit names and lengths using the custom argument provider.
public class MyProvider implements ArgumentsProvider {
@Override
public Stream<Arguments> provideArguments(ExtensionContext context) {
return Stream.of(Arguments.of("apple"), Arguments.of("banana"));
}
}
@ParameterizedTest
@ArgumentsSource(MyProvider.class)
void testFruits(String fruit) {
System.out.println(fruit);
}public class BadProvider implements ArgumentsProvider {
public Stream<Arguments> provideArguments() {
return Stream.of(Arguments.of(1), Arguments.of(2));
}
}public class DoubleProvider implements ArgumentsProvider {
@Override
public Stream<Arguments> provideArguments(ExtensionContext context) {
// Fill in the blank
}
}Pass the test and this pattern moves unknown