0
# CSV Data Sources
1
2
Comprehensive CSV data support for inline data and external files with extensive parsing customization options.
3
4
## Capabilities
5
6
### @CsvSource Annotation
7
8
Provides CSV data inline as test arguments with extensive parsing customization.
9
10
```java { .api }
11
/**
12
* Provides CSV data inline as arguments to parameterized tests
13
*/
14
@Target({ElementType.ANNOTATION_TYPE, ElementType.METHOD})
15
@Retention(RetentionPolicy.RUNTIME)
16
@Documented
17
@API(status = STABLE, since = "5.0")
18
@ArgumentsSource(CsvArgumentsProvider.class)
19
@Repeatable(CsvSources.class)
20
@interface CsvSource {
21
/**
22
* Array of CSV records
23
*/
24
String[] value() default {};
25
26
/**
27
* CSV data as text block (Java 15+ syntax)
28
*/
29
String textBlock() default "";
30
31
/**
32
* Use first row as headers in display names
33
*/
34
boolean useHeadersInDisplayName() default false;
35
36
/**
37
* Quote character for escaping
38
*/
39
char quoteCharacter() default '\'';
40
41
/**
42
* Single character delimiter
43
*/
44
char delimiter() default ',';
45
46
/**
47
* Multi-character delimiter string (takes precedence over delimiter)
48
*/
49
String delimiterString() default "";
50
51
/**
52
* Value to use for empty quoted strings
53
*/
54
String emptyValue() default "";
55
56
/**
57
* Custom strings that represent null values
58
*/
59
String[] nullValues() default "";
60
61
/**
62
* Maximum characters per column (protection against malformed data)
63
*/
64
int maxCharsPerColumn() default 4096;
65
66
/**
67
* Whether to trim whitespace from unquoted values
68
*/
69
boolean ignoreLeadingAndTrailingWhitespace() default true;
70
}
71
```
72
73
**Usage Examples:**
74
75
```java
76
import org.junit.jupiter.params.ParameterizedTest;
77
import org.junit.jupiter.params.provider.CsvSource;
78
79
class CsvSourceExamples {
80
81
// Basic CSV data
82
@ParameterizedTest
83
@CsvSource({
84
"1, apple, true",
85
"2, banana, false",
86
"3, cherry, true"
87
})
88
void testBasicCsv(int id, String name, boolean active) {
89
assertTrue(id > 0);
90
assertNotNull(name);
91
}
92
93
// Custom delimiter
94
@ParameterizedTest
95
@CsvSource(value = {
96
"1|apple|red",
97
"2|banana|yellow",
98
"3|cherry|red"
99
}, delimiter = '|')
100
void testCustomDelimiter(int id, String fruit, String color) {
101
assertTrue(id > 0);
102
assertNotNull(fruit);
103
assertNotNull(color);
104
}
105
106
// Multi-character delimiter
107
@ParameterizedTest
108
@CsvSource(value = {
109
"apple::red::sweet",
110
"lemon::yellow::sour"
111
}, delimiterString = "::")
112
void testMultiCharDelimiter(String fruit, String color, String taste) {
113
assertNotNull(fruit);
114
assertNotNull(color);
115
assertNotNull(taste);
116
}
117
118
// Quoted values with commas
119
@ParameterizedTest
120
@CsvSource({
121
"'John Doe', 'San Francisco, CA', 94102",
122
"'Jane Smith', 'New York, NY', 10001"
123
})
124
void testQuotedValues(String name, String city, int zipCode) {
125
assertTrue(name.contains(" "));
126
assertTrue(city.contains(","));
127
assertTrue(zipCode > 0);
128
}
129
130
// Null and empty value handling
131
@ParameterizedTest
132
@CsvSource(value = {
133
"apple, , sweet", // Empty middle value
134
"banana, yellow, ", // Empty last value
135
"cherry, red, NIL" // Custom null value
136
}, nullValues = {"NIL"}, emptyValue = "EMPTY")
137
void testNullAndEmptyValues(String fruit, String color, String taste) {
138
assertNotNull(fruit);
139
// color and taste may be null or "EMPTY"
140
}
141
142
// Headers in display names
143
@ParameterizedTest(name = "Product: {arguments}")
144
@CsvSource(value = {
145
"ID, Name, Price",
146
"1, Apple, 1.50",
147
"2, Banana, 0.75"
148
}, useHeadersInDisplayName = true)
149
void testWithHeaders(String id, String name, String price) {
150
assertNotNull(id);
151
assertNotNull(name);
152
assertNotNull(price);
153
}
154
155
// Text block syntax (Java 15+)
156
@ParameterizedTest
157
@CsvSource(textBlock = """
158
1, apple, 1.50
159
2, banana, 0.75
160
3, cherry, 2.00
161
""")
162
void testTextBlock(int id, String fruit, double price) {
163
assertTrue(id > 0);
164
assertNotNull(fruit);
165
assertTrue(price > 0);
166
}
167
168
// Whitespace handling
169
@ParameterizedTest
170
@CsvSource(value = {
171
" apple , red ", // Whitespace will be trimmed
172
"' banana ', yellow" // Quoted whitespace preserved
173
}, ignoreLeadingAndTrailingWhitespace = true)
174
void testWhitespaceHandling(String fruit, String color) {
175
// apple will be trimmed, " banana " will preserve spaces
176
assertNotNull(fruit);
177
assertNotNull(color);
178
}
179
}
180
```
181
182
### @CsvFileSource Annotation
183
184
Loads CSV data from classpath resources or file system files.
185
186
```java { .api }
187
/**
188
* Loads CSV data from external files as arguments to parameterized tests
189
*/
190
@Target({ElementType.ANNOTATION_TYPE, ElementType.METHOD})
191
@Retention(RetentionPolicy.RUNTIME)
192
@Documented
193
@API(status = STABLE, since = "5.0")
194
@ArgumentsSource(CsvFileArgumentsProvider.class)
195
@Repeatable(CsvFileSources.class)
196
@interface CsvFileSource {
197
/**
198
* Classpath resources to load CSV data from
199
*/
200
String[] resources() default {};
201
202
/**
203
* File system paths to load CSV data from
204
*/
205
String[] files() default {};
206
207
/**
208
* Character encoding for file reading
209
*/
210
String encoding() default "UTF-8";
211
212
/**
213
* Line separator for parsing
214
*/
215
String lineSeparator() default "\n";
216
217
/**
218
* Number of lines to skip from beginning (e.g., headers)
219
*/
220
int numLinesToSkip() default 0;
221
222
// Inherits all parsing attributes from @CsvSource
223
boolean useHeadersInDisplayName() default false;
224
char quoteCharacter() default '"';
225
char delimiter() default ',';
226
String delimiterString() default "";
227
String emptyValue() default "";
228
String[] nullValues() default "";
229
int maxCharsPerColumn() default 4096;
230
boolean ignoreLeadingAndTrailingWhitespace() default true;
231
}
232
```
233
234
**Usage Examples:**
235
236
```java
237
import org.junit.jupiter.params.ParameterizedTest;
238
import org.junit.jupiter.params.provider.CsvFileSource;
239
240
class CsvFileSourceExamples {
241
242
// Load from classpath resource
243
@ParameterizedTest
244
@CsvFileSource(resources = "/test-data/products.csv")
245
void testFromClasspathResource(int id, String name, double price) {
246
assertTrue(id > 0);
247
assertNotNull(name);
248
assertTrue(price >= 0);
249
}
250
251
// Load from file system
252
@ParameterizedTest
253
@CsvFileSource(files = "src/test/resources/users.csv")
254
void testFromFile(String username, String email, int age) {
255
assertNotNull(username);
256
assertTrue(email.contains("@"));
257
assertTrue(age >= 0);
258
}
259
260
// Skip header rows
261
@ParameterizedTest
262
@CsvFileSource(
263
resources = "/test-data/products-with-headers.csv",
264
numLinesToSkip = 1
265
)
266
void testSkipHeaders(int id, String name, double price) {
267
assertTrue(id > 0);
268
assertNotNull(name);
269
assertTrue(price >= 0);
270
}
271
272
// Custom encoding and delimiter
273
@ParameterizedTest
274
@CsvFileSource(
275
resources = "/test-data/international.csv",
276
encoding = "UTF-8",
277
delimiter = ';'
278
)
279
void testCustomEncodingAndDelimiter(String name, String country, String currency) {
280
assertNotNull(name);
281
assertNotNull(country);
282
assertNotNull(currency);
283
}
284
285
// Multiple files
286
@ParameterizedTest
287
@CsvFileSource(resources = {
288
"/test-data/products-q1.csv",
289
"/test-data/products-q2.csv"
290
})
291
void testMultipleFiles(int id, String name, double price) {
292
assertTrue(id > 0);
293
assertNotNull(name);
294
assertTrue(price >= 0);
295
}
296
297
// With custom null values
298
@ParameterizedTest
299
@CsvFileSource(
300
resources = "/test-data/incomplete-data.csv",
301
nullValues = {"N/A", "NULL", ""}
302
)
303
void testWithNullValues(String name, String value, String category) {
304
assertNotNull(name); // name should never be null
305
// value and category may be null based on nullValues
306
}
307
}
308
```
309
310
### CSV Parsing Exception
311
312
Exception thrown when CSV parsing fails due to malformed data or configuration issues.
313
314
```java { .api }
315
/**
316
* Exception thrown when CSV parsing fails
317
*/
318
@API(status = STABLE, since = "5.0")
319
class CsvParsingException extends JUnitException {
320
/**
321
* Constructs exception with message
322
*/
323
CsvParsingException(String message) { }
324
325
/**
326
* Constructs exception with message and cause
327
*/
328
CsvParsingException(String message, Throwable cause) { }
329
}
330
```
331
332
### Container Annotations
333
334
Container annotations for multiple CSV source annotations.
335
336
```java { .api }
337
/**
338
* Container annotation for multiple @CsvSource annotations
339
*/
340
@Target({ElementType.ANNOTATION_TYPE, ElementType.METHOD})
341
@Retention(RetentionPolicy.RUNTIME)
342
@Documented
343
@API(status = STABLE, since = "5.0")
344
@interface CsvSources {
345
CsvSource[] value();
346
}
347
348
/**
349
* Container annotation for multiple @CsvFileSource annotations
350
*/
351
@Target({ElementType.ANNOTATION_TYPE, ElementType.METHOD})
352
@Retention(RetentionPolicy.RUNTIME)
353
@Documented
354
@API(status = STABLE, since = "5.0")
355
@interface CsvFileSources {
356
CsvFileSource[] value();
357
}
358
```
359
360
**Advanced CSV Features:**
361
362
```java
363
class AdvancedCsvExamples {
364
365
// Complex CSV with various data types
366
@ParameterizedTest
367
@CsvSource({
368
"1, 'Product A', 19.99, true, 2023-01-15",
369
"2, 'Product B', 29.50, false, 2023-02-20",
370
"3, 'Product \"Special\"', 39.99, true, 2023-03-10"
371
})
372
void testComplexCsv(int id, String name, double price, boolean available, String date) {
373
assertTrue(id > 0);
374
assertNotNull(name);
375
assertTrue(price > 0);
376
assertNotNull(date);
377
}
378
379
// Handling special characters and escaping
380
@ParameterizedTest
381
@CsvSource(value = {
382
"apple|'red, juicy'|1.50",
383
"banana|yellow|0.75",
384
"cherry|'dark red'|2.00"
385
}, delimiter = '|')
386
void testSpecialCharacters(String fruit, String description, double price) {
387
assertNotNull(fruit);
388
assertNotNull(description);
389
assertTrue(price > 0);
390
}
391
}
392
```
393
394
The CSV sources provide powerful data-driven testing capabilities with fine-grained control over parsing behavior, making them ideal for complex test scenarios with structured data.