How do I use @CsvSource in JUnit parameterized tests?

To use @CsvSource in JUnit 5 parameterized tests, you define multiple sets of comma-separated input values directly inside the annotation. Each CSV row becomes one test invocation.

1. Add the Required Imports

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

import static org.junit.jupiter.api.Assertions.assertEquals;

@CsvSource is part of JUnit Jupiter Params, so make sure your project includes the parameterized test dependency.

For Maven:

<dependency>
    <groupId>org.junit.jupiter</groupId>
    <artifactId>junit-jupiter-params</artifactId>
    <version>5.11.0</version>
    <scope>test</scope>
</dependency>

For Gradle:

testImplementation 'org.junit.jupiter:junit-jupiter-params:5.11.0'

2. Basic @CsvSource Example

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

import static org.junit.jupiter.api.Assertions.assertEquals;

class CalculatorTest {

    @ParameterizedTest
    @CsvSource({
        "1, 2, 3",
        "5, 7, 12",
        "10, 20, 30"
    })
    void shouldAddTwoNumbers(int a, int b, int expected) {
        int result = a + b;

        assertEquals(expected, result);
    }
}

Each line in @CsvSource maps to the method parameters:

"1, 2, 3"  -> a = 1, b = 2, expected = 3
"5, 7, 12" -> a = 5, b = 7, expected = 12

3. Using Strings with @CsvSource

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

import static org.junit.jupiter.api.Assertions.assertEquals;

class StringTest {

    @ParameterizedTest
    @CsvSource({
        "java, JAVA",
        "junit, JUNIT",
        "test, TEST"
    })
    void shouldConvertTextToUppercase(String input, String expected) {
        assertEquals(expected, input.toUpperCase());
    }
}

JUnit automatically converts CSV values to the method parameter types when possible.

4. Handling Commas in Values

If a value contains a comma, wrap it in single quotes:

@ParameterizedTest
@CsvSource({
    "'Smith, John', John",
    "'Doe, Jane', Jane"
})
void shouldExtractFirstName(String fullName, String firstName) {
    String result = fullName.substring(fullName.indexOf(",") + 2);

    assertEquals(firstName, result);
}

Here, 'Smith, John' is treated as one argument instead of two.

5. Using Custom Delimiters

By default, @CsvSource uses a comma. You can change the delimiter:

@ParameterizedTest
@CsvSource(
    value = {
        "1|2|3",
        "4|5|9",
        "10|20|30"
    },
    delimiter = '|'
)
void shouldAddNumbersWithCustomDelimiter(int a, int b, int expected) {
    assertEquals(expected, a + b);
}

6. Null and Empty Values

JUnit treats an unquoted empty value as null:

@ParameterizedTest
@CsvSource({
    "apple, APPLE",
    ", UNKNOWN"
})
void shouldHandleNullValues(String input, String expected) {
    String result = input == null ? "UNKNOWN" : input.toUpperCase();

    assertEquals(expected, result);
}

You can use an empty string by quoting it:

@ParameterizedTest
@CsvSource({
    "'', empty"
})
void shouldHandleEmptyString(String input, String expected) {
    String result = input.isEmpty() ? "empty" : input;

    assertEquals(expected, result);
}

7. Adding Display Names

You can make test output easier to read using the name attribute:

@ParameterizedTest(name = "{index} => input={0}, expected={1}")
@CsvSource({
    "java, JAVA",
    "junit, JUNIT"
})
void shouldConvertToUppercase(String input, String expected) {
    assertEquals(expected, input.toUpperCase());
}

Example display names:

1 => input=java, expected=JAVA
2 => input=junit, expected=JUNIT

Key Points

  • Use @ParameterizedTest, not @Test.
  • Use @CsvSource to provide multiple comma-separated argument sets.
  • Each CSV row must match the number of method parameters.
  • JUnit automatically converts values to types like int, double, boolean, String, and enums.
  • Use single quotes for values containing commas.
  • Use quoted empty strings for ""; unquoted empty values are treated as null.
  • Use delimiter if comma-separated data is hard to read.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.