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
@CsvSourceto 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 asnull. - Use
delimiterif comma-separated data is hard to read.
