Labs ICT
โญ Pro Login

@ParameterizedTest

Writing the same test logic over and over with different inputs is tedious and error-prone. @ParameterizedTest lets you run the same test method multiple times with different arguments. It is one of JUnit 5's most powerful features.

Your First Parameterized Test


import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;

class ParameterizedTestDemo {

    @ParameterizedTest
    @ValueSource(strings = {"racecar", "radar", "level"})
    void shouldDetectPalindromes(String word) {
        assertTrue(isPalindrome(word));
    }

    @ParameterizedTest
    @ValueSource(ints = {1, 2, 3, 4, 5})
    void shouldAcceptPositiveNumbers(int number) {
        assertTrue(number > 0);
    }
}
    

Each value in @ValueSource is passed as an argument to the test method. The test runs once for each value. So the palindrome test runs 3 times, the numbers test runs 5 times.

Adding Display Names


@ParameterizedTest(name = "palindrome check: \"{0}\"")
@ValueSource(strings = {"racecar", "radar", "level"})
void palindromes(String word) {
    assertTrue(isPalindrome(word));
}

@ParameterizedTest(name = "input: {0}")
@ValueSource(ints = {1, 2, 3, 4, 5})
void positiveNumbers(int number) {
    assertTrue(number > 0);
}
    

Multiple Arguments

Some sources provide multiple arguments per invocation:


@ParameterizedTest
@CsvSource({
    "1, 2, 3",
    "5, 5, 10",
    "0, 0, 0",
    "-1, 1, 0"
})
void addition(int a, int b, int expected) {
    assertEquals(expected, calc.add(a, b));
}

@ParameterizedTest
@CsvSource({
    "hello, HELLO",
    "world, WORLD",
    "junit, JUNIT"
})
void upperCase(String input, String expected) {
    assertEquals(expected, input.toUpperCase());
}
    

Available Sources


@ValueSource          - Single values (strings, ints, etc.)
@CsvSource            - Comma-separated values
@CsvFileSource        - CSV file input
@MethodSource         - Method that provides arguments
@EnumSource           - Enum values
@ArgumentsSource      - Custom argument provider
    

@MethodSource

For complex arguments, use a static method to provide them:


@ParameterizedTest
@MethodSource("stringProvider")
void withMethodSource(String argument) {
    assertNotNull(argument);
}

static Stream<String> stringProvider() {
    return Stream.of("apple", "banana", "cherry");
}

@ParameterizedTest
@MethodSource("additionCases")
void addition(int a, int b, int expected) {
    assertEquals(expected, calc.add(a, b));
}

static Stream<Arguments> additionCases() {
    return Stream.of(
        Arguments.of(1, 2, 3),
        Arguments.of(5, 5, 10),
        Arguments.of(-1, 1, 0)
    );
}
    

@EnumSource


@ParameterizedTest
@EnumSource(TimeUnit.class)
void allTimeUnits(TimeUnit unit) {
    assertNotNull(unit.name());
    assertTrue(unit.toMillis(1) > 0);
}

@ParameterizedTest
@EnumSource(value = TimeUnit.class, names = {"SECONDS", "MINUTES"})
void selectedTimeUnits(TimeUnit unit) {
    assertEquals(TimeUnit.SECONDS, unit);
}
    

@CsvFileSource


// data.csv:
// input,expected
// "hello",5
// "world",5
// "junit",5
// "",0

@ParameterizedTest
@CsvFileSource(resources = "/data.csv", numLinesToSkip = 1)
void wordLength(String input, int expected) {
    assertEquals(expected, input.length());
}
    

Best Practices

  • Use meaningful parameter names with @ParameterizedTest(name = ...)
  • Combine with @DisplayName for even better readability
  • Keep each test case simple โ€” one assertion per parameterized test
  • Use @CsvFileSource for large test data sets
  • Avoid parameterized tests with more than 3-4 arguments per invocation

๐Ÿงช Quick Quiz

Which annotation marks a method as a parameterized test?