We use @ArgumentsSource to supply test methods with custom sets of data. This helps us run the same test many times with different inputs, making sure our code works well in all cases.
0
0
@ArgumentsSource with custom providers in JUnit
Introduction
When you want to test a method with many different inputs that are not simple constants.
When your test data needs to be generated dynamically or comes from a complex source.
When you want to keep your test code clean by separating data generation from test logic.
When built-in sources like <code>@ValueSource</code> or <code>@CsvSource</code> are not enough.
When you want to reuse the same data provider for multiple test methods.
Syntax
JUnit
@ArgumentsSource(MyArgumentsProvider.class) void testMethod(Type param) { // test code } class MyArgumentsProvider implements ArgumentsProvider { @Override public Stream<? extends Arguments> provideArguments(ExtensionContext context) { // return Stream of Arguments } }
The @ArgumentsSource annotation takes a class that implements ArgumentsProvider.
The provideArguments method returns a Stream of Arguments objects, each representing one set of parameters.
Examples
This example runs the test twice, once with "apple" and once with "banana" as input.
JUnit
@ArgumentsSource(MyArgsProvider.class) void testWithCustomData(String input) { assertNotNull(input); } class MyArgsProvider implements ArgumentsProvider { @Override public Stream<? extends Arguments> provideArguments(ExtensionContext context) { return Stream.of(Arguments.of("apple"), Arguments.of("banana")); } }
This example tests numbers 1, 2, and 3 to check if they are greater than zero.
JUnit
@ArgumentsSource(NumberProvider.class) void testNumbers(int number) { assertTrue(number > 0); } class NumberProvider implements ArgumentsProvider { @Override public Stream<? extends Arguments> provideArguments(ExtensionContext context) { return IntStream.rangeClosed(1, 3).mapToObj(Arguments::of); } }
Sample Program
This test runs four times with even numbers 2, 4, 6, and 8. Each time it checks if the number is even.
JUnit
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 CustomArgumentsSourceTest { @ParameterizedTest @ArgumentsSource(EvenNumberProvider.class) void testEvenNumbers(int number) { assertTrue(number % 2 == 0, "Number should be even"); } static class EvenNumberProvider implements ArgumentsProvider { @Override public Stream<? extends Arguments> provideArguments(ExtensionContext context) { return Stream.of(2, 4, 6, 8).map(Arguments::of); } } }
OutputSuccess
Important Notes
Make sure your ArgumentsProvider class is static or top-level and public if used outside the test class.
Each Arguments object can hold multiple parameters if your test method has more than one argument.
Use Stream.of or other stream sources to generate test data flexibly.
Summary
@ArgumentsSource lets you provide custom test data for parameterized tests.
You create a class implementing ArgumentsProvider to supply data.
This helps test many cases cleanly and flexibly.