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.
@ArgumentsSource with custom providers in 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.
@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")); } }
@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); } }
This test runs four times with even numbers 2, 4, 6, and 8. Each time it checks if the number is even.
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); } } }
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.
@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.
Practice
@ArgumentsSource in JUnit tests?Solution
Step 1: Understand the role of
This annotation is used to supply custom arguments to parameterized tests by referencing a class that implements@ArgumentsSourceArgumentsProvider.Step 2: Differentiate from other annotations
Other options like disabling tests or ordering are handled by different annotations, not@ArgumentsSource.Final Answer:
To provide custom test data from a class implementingArgumentsProvider-> Option BQuick Check:
@ArgumentsSourcesupplies custom test data [OK]
@ArgumentsSource links to custom data providers [OK]- Confusing
@ArgumentsSourcewith@Disabled - Thinking it controls test order
- Assuming it injects mocks
ArgumentsProvider class for use with @ArgumentsSource?Solution
Step 1: Check interface implementation and method signature
The class must implementArgumentsProviderand overrideprovideArguments(ExtensionContext)returning aStream<Arguments>.Step 2: Validate return type and method parameters
public class MyProvider implements ArgumentsProvider { public Stream<Arguments> provideArguments(ExtensionContext context) { return Stream.of(Arguments.of(1)); } } correctly implements the interface and method signature. public class MyProvider { public Stream<Arguments> provideArguments() { return Stream.of(Arguments.of(1)); } } misses the interface and method parameter. public class MyProvider implements ArgumentsSource { public Stream<Arguments> provideArguments() { return Stream.of(Arguments.of(1)); } } wrongly implementsArgumentsSourcewhich is an annotation, not an interface. public class MyProvider implements ArgumentsProvider { public List<Arguments> provideArguments() { return List.of(Arguments.of(1)); } } returns a List instead of a Stream.Final Answer:
public class MyProvider implements ArgumentsProvider { public Stream<Arguments> provideArguments(ExtensionContext context) { return Stream.of(Arguments.of(1)); } } -> Option AQuick Check:
ImplementArgumentsProviderwith correct method signature [OK]
ArgumentsProvider with provideArguments(ExtensionContext) [OK]- Forgetting to implement
ArgumentsProvider - Wrong method signature or missing parameter
- Returning List instead of Stream
- Confusing
ArgumentsSourceannotation with interface
public class NumberProvider implements ArgumentsProvider {
public Stream<Arguments> provideArguments(ExtensionContext context) {
return Stream.of(Arguments.of(2), Arguments.of(4));
}
}
@ParameterizedTest
@ArgumentsSource(NumberProvider.class)
void testIsEven(int number) {
assertTrue(number % 2 == 0);
}Solution
Step 1: Analyze the provided arguments
The provider returns two arguments: 2 and 4, both even numbers.Step 2: Check the assertion logic
The test asserts that the number modulo 2 equals 0, which is true for both 2 and 4.Final Answer:
Both tests pass because 2 and 4 are even numbers -> Option CQuick Check:
2 % 2 == 0 and 4 % 2 == 0 [OK]
- Assuming 4 is odd
- Ignoring the assertion logic
- Confusing test failure with compilation error
ArgumentsProvider implementation:public class StringProvider implements ArgumentsProvider {
public List<Arguments> provideArguments(ExtensionContext context) {
return List.of(Arguments.of("test"));
}
}Solution
Step 1: Check the return type of
TheprovideArgumentsArgumentsProviderinterface requiresprovideArgumentsto return aStream<Arguments>, but the code returns aList<Arguments>.Step 2: Validate interface and method name
The class correctly implementsArgumentsProviderand the method name is correct.Final Answer:
Method should return Stream<Arguments>, not List<Arguments> -> Option DQuick Check:
Return type must be Stream<Arguments> [OK]
provideArguments returns Stream, not List [OK]- Returning List instead of Stream
- Confusing interface with annotation
- Wrong method name
@ArgumentsSource with a custom provider that supplies pairs. Which of the following ArgumentsProvider implementations correctly provides pairs of integers for the test?Solution
Step 1: Understand the test method parameters
The test method expects two integer parameters per test invocation, so eachArgumentsmust supply two integers.Step 2: Evaluate each provider's argument format
public class PairProvider implements ArgumentsProvider { public Stream<Arguments> provideArguments(ExtensionContext context) { return Stream.of(Arguments.of(1, 2), Arguments.of(3, 4)); } } correctly provides pairs of integers as separate arguments. public class PairProvider implements ArgumentsProvider { public Stream<Arguments> provideArguments(ExtensionContext context) { return Stream.of(Arguments.of(new int[]{1, 2}), Arguments.of(new int[]{3, 4})); } } provides arrays which may not match the method signature expecting two int parameters. public class PairProvider implements ArgumentsProvider { public Stream<Arguments> provideArguments(ExtensionContext context) { return Stream.of(Arguments.of(List.of(1, 2)), Arguments.of(List.of(3, 4))); } } provides lists which also do not match two int parameters directly. public class PairProvider implements ArgumentsProvider { public Stream<Arguments> provideArguments(ExtensionContext context) { return Stream.of(Arguments.of(1), Arguments.of(2), Arguments.of(3), Arguments.of(4)); } } provides single integers, not pairs.Final Answer:
public class PairProvider implements ArgumentsProvider { public Stream<Arguments> provideArguments(ExtensionContext context) { return Stream.of(Arguments.of(1, 2), Arguments.of(3, 4)); } } -> Option AQuick Check:
Each Arguments.of() must match method parameters [OK]
- Passing arrays or lists instead of separate parameters
- Providing single arguments when pairs are needed
- Not matching argument count to method parameters
Ready to prove it?
Pass the test and this pattern moves unknown
