Parameterized Test
About
A @ParameterizedTest
is a test method in JUnit 5 that runs multiple times with different arguments. Instead of duplicating test code with different input values, parameterized tests allow you to write a single test method that automatically receives different input values and runs multiple times.
This improves test readability and maintainability.
Why Use Parameterized Tests?
Reduce duplication in test code.
Cover more input cases with less effort.
Improve test coverage and reliability.
1. @ValueSource
– Single Literal Values
@ValueSource
– Single Literal ValuesUse @ValueSource
when we want to run a test multiple times with a single argument of the same type (e.g., all integers or all strings). It is ideal for primitive or simple input validation.
Basic Usage
@ParameterizedTest
@ValueSource(ints = {1, 2, 3})
void testWithInt(int number) {
assertTrue(number > 0);
}
Advanced Usage
Supported types:
int
,long
,double
,short
,byte
,char
,boolean
,String
,Class<?>
Limitation: Only one parameter is allowed.
Passing
null
: Not supported directly. You must use@NullSource
or@NullAndEmptySource
.
Handling Nulls and Edge Cases
@ParameterizedTest
@NullSource
@EmptySource
@ValueSource(strings = {"abc", " "})
void testStringInputs(String input) {
assertNotNull(input);
}
@NullSource
→ adds one null argument.@EmptySource
→ adds empty value (""
, empty collection/array).
2. @CsvSource
@CsvSource
Use @CsvSource
to test methods with multiple parameters. The values are given inline in a CSV format. It improves clarity when testing combinations of inputs.
Inline CSV Data
Basic Usage
@ParameterizedTest
@CsvSource({
"apple, 1",
"banana, 2"
})
void testWithCsvSource(String fruit, int quantity) {
assertNotNull(fruit);
assertTrue(quantity > 0);
}
Advanced Usage
String values with commas: Use quotes.
@CsvSource({ "'apple, red', 1", "'banana, ripe', 2" })
Null values: Use
null
as a literal string (quotes are required).@CsvSource({ "apple, 1", "null, 0" }) void testNulls(String fruit, int quantity) { assertTrue(fruit == null || fruit.length() > 0); }
Load Data from CSV File
Basic Usage
@ParameterizedTest
@CsvFileSource(resources = "/sample-data.csv", numLinesToSkip = 1)
void testWithFile(String name, int age) {
assertTrue(age > 0);
}
Advanced Usage
File format: CSV file must be on the classpath.
Quotes can be used to handle commas inside values.
Skipping header: Use
numLinesToSkip = 1
.Custom delimiters: Use
delimiter = ';'
for semi-colon delimited files.
4. @EnumSource
– Use Enum Constants
@EnumSource
– Use Enum ConstantsUse @EnumSource
when testing logic based on different enum values. It ensures all or selected enum constants are covered.
Basic Usage
enum Role { ADMIN, USER, GUEST }
@ParameterizedTest
@EnumSource(Role.class)
void testWithEnum(Role role) {
assertNotNull(role);
}
Advanced Usage
Include specific constants:
@EnumSource(value = Role.class, names = {"ADMIN", "USER"})
Exclude constants using regex:
@EnumSource(value = Role.class, mode = EnumSource.Mode.EXCLUDE, names = {"GUEST"})
5. @MethodSource
– Arguments from a Factory Method
@MethodSource
– Arguments from a Factory MethodUse @MethodSource
when test arguments are dynamic, complex, or require logic to generate. It supports multiple parameters and null
.
Basic Usage
@ParameterizedTest
@MethodSource("stringProvider")
void testWithMethodSource(String value) {
assertNotNull(value);
}
static Stream<String> stringProvider() {
return Stream.of("java", "junit", "spring");
}
Multiple Parameters
@ParameterizedTest
@MethodSource("multiParamProvider")
void testWithMultipleParams(String input, int length) {
assertEquals(length, input.length());
}
static Stream<Arguments> multiParamProvider() {
return Stream.of(
Arguments.of("a", 1),
Arguments.of("ab", 2)
);
}
Advanced Usage
Nullable arguments: We can pass
null
safely.static Stream<Arguments> nullProvider() { return Stream.of( Arguments.of("test", 4), Arguments.of(null, 0) ); }
Dynamic generation using files, DB, or API:
static Stream<Arguments> dynamicProvider() throws IOException { return Files.lines(Path.of("data.txt")) .map(line -> Arguments.of(line)); }
6. @ArgumentsSource
– Custom Provider
@ArgumentsSource
– Custom ProviderUse @ArgumentsSource
when you want to provide parameters from a custom provider class. It's useful for reading from a DB, API, or complex logic.
Basic Usage
Example 1: Hardcoded List of Strings
@ParameterizedTest
@ArgumentsSource(FixedStringProvider.class)
void testWithFixedStrings(String input) {
assertNotNull(input);
}
static class FixedStringProvider implements ArgumentsProvider {
@Override
public Stream<? extends Arguments> provideArguments(ExtensionContext context) {
return Stream.of("apple", "banana", "cherry").map(Arguments::of);
}
}
Example 2: Providing Multiple Parameters
@ParameterizedTest
@ArgumentsSource(MultiArgProvider.class)
void testWithMultipleArgs(String name, int age) {
assertNotNull(name);
assertTrue(age > 0);
}
static class MultiArgProvider implements ArgumentsProvider {
@Override
public Stream<? extends Arguments> provideArguments(ExtensionContext context) {
return Stream.of(
Arguments.of("Alice", 30),
Arguments.of("Bob", 25),
Arguments.of("Charlie", 40)
);
}
}
Example 3: Random Data Generator
@ParameterizedTest
@ArgumentsSource(RandomIntProvider.class)
void testWithRandomInts(int value) {
assertTrue(value >= 0 && value <= 100);
}
static class RandomIntProvider implements ArgumentsProvider {
@Override
public Stream<? extends Arguments> provideArguments(ExtensionContext context) {
Random random = new Random();
return Stream.generate(() -> Arguments.of(random.nextInt(101)))
.limit(5); // 5 random values
}
}
Example 4: Reading from a File
@ParameterizedTest
@ArgumentsSource(FileLineProvider.class)
void testFromFile(String line) {
assertFalse(line.trim().isEmpty());
}
static class FileLineProvider implements ArgumentsProvider {
@Override
public Stream<? extends Arguments> provideArguments(ExtensionContext context) throws Exception {
Path path = Paths.get("src/test/resources/testdata.txt");
return Files.lines(path).map(Arguments::of);
}
}
Example 5: Generating Null and Edge Cases
@ParameterizedTest
@ArgumentsSource(NullEdgeCaseProvider.class)
void testWithEdgeCases(String input) {
// handle null, empty, normal
}
static class NullEdgeCaseProvider implements ArgumentsProvider {
@Override
public Stream<? extends Arguments> provideArguments(ExtensionContext context) {
return Stream.of(
Arguments.of((String) null),
Arguments.of(""),
Arguments.of("valid")
);
}
}
Advanced Usage
Useful when input comes from:
External services
Complex business logic
Random generators
We can inject dependencies into the provider if needed via Spring or custom mechanisms.
Last updated
Was this helpful?