skip to content

In a JUnit 5 @CsvSource row, what value does the test method receive for a column that is left empty, and how do you deliberately pass an empty String or a null using the nullValues and emptyValue attributes?

level: middleimportance: should knowfreq 46%

answer

  1. Unquoted empty → null, always
  2. Quoted '' → emptyValue (default empty String)
  3. emptyValue does not affect unquoted blanks
  4. nullValues = {"NIL","N/A"} → extra null tokens
  5. null cannot bind to int — use Integer

basics

~20 s

An unquoted empty column becomes null. A quoted empty column ('') becomes the emptyValue, which defaults to the empty String. Use emptyValue to substitute something else, and nullValues to list tokens such as NIL or N/A that should also convert to null.

solid answer

~40 s

Two rules cover it: - **Unquoted empty → `null`.** `"a, , c"` passes `null` for the middle parameter, always — `emptyValue` does not change this. - **Quoted empty → `emptyValue`.** `"a, '', c"` passes whatever `emptyValue` is set to, and its default is the empty String `""`. So the distinction between "nothing" and "an empty string" is expressed by the quotes, which is the part candidates get wrong. `nullValues` adds custom null tokens: `@CsvSource(nullValues = {"NIL", "N/A"}, ...)` makes those cells arrive as `null` — handy when the CSV is human-authored or exported from a spreadsheet. A practical consequence: `null` can only bind to a reference parameter. `@CsvSource({"1, "})` against `(int a, int b)` fails, because `null` cannot be unboxed to `int`; declare `Integer` when a column may be absent.

code

java · 11 lines
java
@ParameterizedTest
@CsvSource(nullValues = "NIL", textBlock = """
    NIL,     false
    ,        false
    '',      false
    '   ',   false
    alice,   true
    """)
void rejectsBlankNames(String name, boolean valid) {
    assertEquals(valid, UserValidator.isValidName(name));
}

go deeper

for a junior

Memorise the pair: blank means null, '' means empty string. That alone answers most screening versions of this question.

for a middle

Add emptyValue and nullValues, and note that emptyValue never rescues an unquoted blank.

for a senior

Bring the primitive-unboxing failure and the design habit of covering null, empty and whitespace-only in one table when testing validators.

for a principal

Frame it as fixture legibility — explicit NIL tokens beat invisible blank cells in files other people edit, and the parameter type is a contract across every row.

## Why this exists CSV has no type system and no concept of "absent". A cell is either some characters or no characters, so any CSV-based test source has to invent a convention for `null` versus empty string. JUnit 5 picked one and stuck to it, and the convention is the single most-missed detail of `@CsvSource`. ## The two rules **Rule 1 — an unquoted empty value is converted to `null`, unconditionally.** ```java @CsvSource({"apple, , 1"}) // second parameter receives null ``` This holds *regardless* of the `emptyValue` attribute. The documentation is explicit about it, and it is the behaviour that trips people up when they set `emptyValue` expecting it to catch blank cells. **Rule 2 — a quoted empty value is converted to `emptyValue`, which defaults to the empty String.** ```java @CsvSource({"apple, '', 1"}) // second parameter receives "" ``` Remember `@CsvSource`'s quote character is the single quote `'`, so `''` is the quoted-empty spelling. (`@CsvFileSource` uses `"` by default, so there the spelling is `""`.) Together: **the quotes are the type declaration.** Nothing at all means absent; an explicit empty pair means present-but-empty. That is precisely the distinction you usually want to test against a validator or a parser. ## emptyValue `emptyValue` changes what a *quoted empty* cell becomes: ```java @ParameterizedTest @CsvSource(emptyValue = "EMPTY", textBlock = """ apple, '', 1 banana, , 2 """) void check(String fruit, String note, int rank) { } ``` Row one gives `note = "EMPTY"`. Row two still gives `note = null`. Use it when the empty string is awkward to read in a fixture, or when the parameter type needs a sentinel rather than a blank. ## nullValues `nullValues` lists textual tokens that should be converted to `null` in addition to the unquoted-empty case: ```java @CsvSource(nullValues = {"NIL", "N/A"}, textBlock = """ apple, 1 NIL, 0 N/A, -1 """) ``` Rows two and three pass `null` for the first parameter. This matters most with `@CsvFileSource`, where the file is often exported from a spreadsheet or written by a non-developer who typed `N/A`, and with tables where a literal blank cell would be invisible in review. An explicit `NIL` token is self-documenting in a way an empty gap between two commas is not. One subtlety: matching happens on the *trimmed, unquoted* token. If a cell is quoted — `'NIL'` — it is a literal string, not a null. That gives you a way to test the string `"NIL"` in the same table that uses `NIL` as a null marker. ## Nulls and primitive parameters `null` cannot be converted to a primitive. This fails: ```java @ParameterizedTest @CsvSource({"1, "}) void bad(int a, int b) { } // cannot unbox null into int ``` The failure message is about argument conversion, and the fix is to declare the nullable column as a wrapper type — `Integer b` — or as `String` if the test is about parsing. Any column that may be blank in *any* row must have a reference-typed parameter, because the parameter type is fixed for the whole table. The same applies to enum and `java.time` parameters — those are reference types, so `null` binds fine. ## Practical patterns - **Validation tables.** A single `@CsvSource` covering `null`, `''`, whitespace-only and a valid value is a compact, complete test of an input validator — and the three degenerate cases are spelled `,`, `''` and `' '` respectively (the last needs quoting, otherwise trimming would erase it into `null`). - **Optional fields.** Model an absent field as an unquoted blank and declare the parameter as a wrapper or `String`. - **Human-maintained files.** Set `nullValues = {"", "N/A", "NULL"}` so a spreadsheet export behaves predictably no matter how the author expressed "nothing". ## What to say in an interview State the two rules crisply, note that `emptyValue` does *not* rescue an unquoted blank, mention `nullValues` for custom tokens, and finish with the primitive-parameter consequence. That sequence covers the mechanism and the failure mode people actually hit.

  • If you set emptyValue = "EMPTY", what does an unquoted blank column produce?
    Still `null`. `emptyValue` only applies to a *quoted* empty value such as `''`; an unquoted empty cell is converted to a null reference regardless of the attribute. If you want blanks to become the sentinel, either quote them in the table or add the sentinel handling in the test.
  • Why does @CsvSource({"1, "}) fail against a method declaring (int a, int b)?
    The blank column is converted to `null`, and `null` cannot be unboxed into the primitive `int`, so argument conversion fails for that invocation. Declaring the parameter as `Integer` fixes it. Because the parameter type is fixed for the whole table, any column that is blank in even one row must be reference-typed.

saying these in an interview costs you the question

  • Saying an unquoted empty cell yields an empty String
  • Expecting emptyValue to convert unquoted blanks
  • Thinking nullValues is needed before any cell can be null
  • Using a primitive parameter for a column that is blank in some rows
  • Assuming a quoted 'NIL' is still treated as a null token

context