← Recipes

阅读中文版本

Parametrize JUnit 5 Tests with a Method Source

Drive JUnit 5 parameterised tests from a method source or CSV so edge cases stay explicit and addable without new methods.

~30 mintestingjavajunit

Task

Convert repeated assertions into JUnit 5 parameterised tests fed by a method source.

When to use this

A validation function has a dozen hand-written test methods that differ only by input and expected result.

Prerequisites

  • Java 17 with JUnit 5
  • A function under test with clear inputs and outputs
  • A Maven or Gradle build

Steps

1. Feed inputs from a method source.

@ParameterizedTest
@MethodSource("cases")
void validates(String input, boolean expected) {
    assertEquals(expected, Validator.isValid(input));
}
static Stream<Arguments> cases() {
    return Stream.of(
        Arguments.of("ok", true),
        Arguments.of("", false),
        Arguments.of("bad!", false));
}

Expected output: One test method covers every case and each failure names the offending input.

2. Add CSV rows for readability when cases are tabular.

@ParameterizedTest
@CsvSource({"ok,true", "'',false", "bad!,false"})
void validatesCsv(String input, boolean expected) {
    assertEquals(expected, Validator.isValid(input));
}

Expected output: Tabular cases are editable like data, not code.

Troubleshooting

Problem

Failure output unclear

Solution

Name each case or split sources so the failing argument is visible.

Problem

Tests not discovered

Solution

Ensure the parameterized dependency is present and the source method is static.

Limitations

  • Does not suit tests with very different setup per case.
  • Argument order mistakes can hide failures.
  • Requires readable case names for diagnosis.

What this recipe does

Convert repeated assertions into JUnit 5 parameterised tests fed by a method source.

A validation function has a dozen hand-written test methods that differ only by input and expected result.

Prerequisites

  • Java 17 with JUnit 5
  • A function under test with clear inputs and outputs
  • A Maven or Gradle build

Procedure

  1. Feed inputs from a method source.
@ParameterizedTest
@MethodSource("cases")
void validates(String input, boolean expected) {
    assertEquals(expected, Validator.isValid(input));
}
static Stream<Arguments> cases() {
    return Stream.of(
        Arguments.of("ok", true),
        Arguments.of("", false),
        Arguments.of("bad!", false));
}

Expected result: One test method covers every case and each failure names the offending input.

  1. Add CSV rows for readability when cases are tabular.
@ParameterizedTest
@CsvSource({"ok,true", "'',false", "bad!,false"})
void validatesCsv(String input, boolean expected) {
    assertEquals(expected, Validator.isValid(input));
}

Expected result: Tabular cases are editable like data, not code.

How to confirm it worked

Run the commands above and confirm every expected result in order. If a step does not produce the stated output, use the troubleshooting notes before continuing. A passing run shows adding a new case is a one-line data change and failures identify the exact input that broke.

Troubleshooting

Failure output unclear — Name each case or split sources so the failing argument is visible.

Tests not discovered — Ensure the parameterized dependency is present and the source method is static.

Limitations

  • Does not suit tests with very different setup per case.
  • Argument order mistakes can hide failures.
  • Requires readable case names for diagnosis.