Labs ICT
โญ Pro Login

@ParameterizedTest

2 min read | JUnit Testing
โญ

Want the full learning experience?

Get structured courses, certificates, projects, and instructor support with LabsICT Pro.

Explore Pro Courses

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?