0
0
JUnittesting~15 mins

Custom argument providers in JUnit - Build an Automation Script

Choose your learning style9 modes available
Automate a parameterized test using a custom argument provider in JUnit
Preconditions (2)
Step 1: Create a custom argument provider class implementing ArgumentsProvider
Step 2: Override provideArguments method to supply test data
Step 3: Create a parameterized test method in the test class
Step 4: Annotate the test method with @ParameterizedTest and @ArgumentsSource with the custom provider
Step 5: Run the test and verify it executes once per data set
✅ Expected Result: The parameterized test runs successfully for each data set provided by the custom argument provider, passing all assertions.
Automation Requirements - JUnit 5
Assertions Needed:
Verify the test method runs for each argument set
Assert the input values are as expected inside the test
Best Practices:
Use @ArgumentsSource annotation with a custom ArgumentsProvider
Implement provideArguments method returning Stream<Arguments>
Keep test data inside the provider class for reusability
Use descriptive test method names
Avoid hardcoding data inside the test method
Automated Solution
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 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.

Common Mistakes - 4 Pitfalls
{'mistake': 'Not implementing ArgumentsProvider interface correctly', 'why_bad': "The test framework won't recognize the provider and tests won't run with parameters.", 'correct_approach': 'Implement ArgumentsProvider and override provideArguments method returning Stream<Arguments>.'}
Hardcoding test data inside the test method instead of the provider
Using incorrect annotation like @ValueSource instead of @ArgumentsSource for custom providers
Returning null or empty stream from provideArguments
Bonus Challenge

Now add data-driven testing with 3 different sets of fruit names and lengths using the custom argument provider.

Show Hint