Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

JUnit 5 calls data-driven testing parameterized testing: annotate a test with @ParameterizedTest, provide an argument source, and JUnit runs the test once for each supplied set of arguments. This lets you check many inputs with one focused test method instead of duplicating the same assertion logic.

How parameterized tests work

A regular JUnit test method is invoked once. A parameterized test is invoked repeatedly, with each invocation receiving arguments from a source such as an annotation, a factory method, or a CSV file. The official JUnit 5 User Guide describes the feature as a way to run a test method multiple times with different arguments.

To create one, add @ParameterizedTest, declare method parameters for the values each invocation needs, and attach at least one argument source. For example, this test checks several strings using the same palindrome logic:

@ParameterizedTest(name = "{index}: {0} is a palindrome")
@ValueSource(strings = {"racecar", "radar", "able was I ere I saw elba"})
void palindromes(String candidate) {
    assertTrue(isPalindrome(candidate));
}

Each value becomes a separate invocation. The display-name pattern includes the invocation index and input, helping identify a failing case in IDE or test-runner output.

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Choose an argument source

Use the source that keeps the cases understandable and maintainable. Inline annotations work well for small, stable sets; method or custom providers are more flexible when data must be computed, shared, or built as objects.

Source Best suited to How data is supplied
@ValueSource A concise set of values for one parameter Literals such as strings, integers, or longs
@EnumSource Testing enum values or a selected subset Enum constants, optionally selected by name
@CsvSource A small inline matrix with multiple values per case Comma-separated records in the annotation; supports headers, custom delimiters, quoting, null markers, and text blocks
@CsvFileSource Cases maintained in a CSV file Rows read from a classpath resource or local file; rows can include headers and comments
@MethodSource Computed, reusable, or object-rich datasets A factory method returning supported streams, primitive streams, collections, iterators, iterables, or arrays
@FieldSource Values maintained in a field rather than a factory method Argument streams or iterable field values; confirm support in the JUnit version pinned by the project
@ArgumentsSource Domain-specific or custom case generation A custom ArgumentsProvider

Use inline CSV for a small case matrix

@CsvSource maps each record to the test method’s parameters in order. It is convenient when readers should see the input and expected result together. Quote a field containing a delimiter so it remains one value:

@ParameterizedTest
@CsvSource({"apple, 1", "banana, 2", "'lemon, lime', 3"})
void ranks(String fruit, int rank) {
    assertNotNull(fruit);
    assertTrue(rank > 0);
}

Here, each row supplies a String and an int. For behavior tests, prefer placing the expected result beside the input and asserting that result; this makes the case matrix explain what each input is supposed to do.

Load cases from a CSV file

Choose @CsvFileSource when the table is large or is maintained separately from the Java test. It can read a classpath resource or local file, and supports headers and comments. Keep the file’s location and format aligned with the source configuration, and make sure the rows still map clearly and consistently to the test method’s parameters.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

A CSV file is most useful when the tabular data is easier to review or update outside Java code. If cases require substantial object setup, conditional generation, or behavior that is clearer in code than in a flat table, a method-based source is usually easier to maintain.

Use a method source for computed or reusable cases

@MethodSource lets a factory create argument sets, including values that need setup or domain objects. For example:

@ParameterizedTest
@MethodSource("cases")
void computesExpected(String input, int expected) {
    assertEquals(expected, calculator(input));
}

static Stream<Arguments> cases() {
    return Stream.of(arguments("A", 1), arguments("BB", 2));
}

The factory method can return a supported stream, collection, iterator, iterable, or array. A method source is also a natural choice when several tests need the same dataset or when deriving cases is clearer than listing each one inline.

Map arguments and control conversion

For sources with multiple values per case, JUnit supplies the values positionally: the first source value goes to the first test parameter, the second to the second, and so on. Common string values can be converted implicitly to the declared target type, such as an integer parameter. Use an explicit converter or an argument aggregator when a value needs more deliberate conversion or must be assembled into a richer object.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

JUnit’s supported parameter ordering allows indexed parameters first, argument aggregators next, and parameters supplied by a ParameterResolver last. When changing a test signature, check that source values and any injected parameters follow this ordering.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Set up the JUnit dependency and check version support

Parameterized tests are provided by the junit-jupiter-params artifact. Include it in the project’s JUnit Jupiter test dependencies; a typical JUnit Jupiter build may already bring it in, but verify the dependencies actually used by your build. JUnit 5 requires Java 8 or higher at runtime, according to the JUnit team’s User Guide.

Annotations and related capabilities evolve across JUnit releases. Check the project’s pinned JUnit version before adopting newer features such as @FieldSource or parameterized classes, rather than assuming they are available in every JUnit 5 build.

Make failures easy to diagnose

  • Keep each invocation focused. Each row should exercise the same behavior with different arguments, not bundle unrelated checks into a single test.
  • Keep expected results beside inputs. A reader should be able to understand why a case exists without searching elsewhere.
  • Name invocations meaningfully. Include an index or key input in the display name so a failed case is identifiable in test output.
  • Choose the simplest maintainable source. Use inline data for a small stable matrix, a CSV file for separately maintained tabular data, and method or custom providers for generated data, reusable fixtures, or domain objects.

Parameterized invocations have the lifecycle of regular JUnit tests: @BeforeEach runs before every invocation, and IDEs report invocations individually. Account for that when setup has side effects or takes significant time.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.