CodeWalk

JUnit 5 Jupiter架构与@ParameterizedTest参数化测试

作者:编译有声 · 2026-05-30 12:55

请详细解释JUnit 5 Jupiter的架构(JUnit Platform + Jupiter + Vintage),以及参数化测试的高级用法。@ParameterizedTest配合@ValueSource/@CsvSource/@MethodSource/@EnumSource等如何实现数据驱动测试?参数化测试中如何自定义参数提供者?

回答

编译有声

JUnit 5三层架构

  1. JUnit Platform:在JVM上启动测试框架的基础,提供TestEngine API
  2. JUnit Jupiter:JUnit 5新编程模型的实现(注解+扩展模型)
  3. JUnit Vintage:提供向后兼容,运行JUnit 3/4的测试

参数化测试

@ValueSource — 简单字面量

@ParameterizedTest
@ValueSource(strings = { "racecar", "radar", "level" })
void testPalindrome(String word) {
    assertTrue(isPalindrome(word));
}

@CsvSource — 多参数CSV

@ParameterizedTest
@CsvSource({
    "apple, 1",
    "banana, 2",
    "'le,mon', 3"  // 逗号用单引号
})
void testWithCsvSource(String fruit, int rank) { ... }

@MethodSource — 工厂方法

@ParameterizedTest
@MethodSource("stringProvider")
void testWithMethodSource(String arg) { ... }

static Stream<String> stringProvider() {
    return Stream.of("foo", "bar");
}

@EnumSource — 枚举

@ParameterizedTest
@EnumSource(value = TimeUnit.class, names = {"DAYS", "HOURS"})
void testWithEnum(TimeUnit unit) { ... }

@ArgumentsSource — 自定义提供者

@ParameterizedTest
@ArgumentsSource(MyArgumentsProvider.class)
void testWithCustomProvider(String arg) { ... }

class MyArgumentsProvider implements ArgumentsProvider {
    @Override
    public Stream<? extends Arguments> provideArguments(
            ExtensionContext context) {
        return Stream.of(Arguments.of("hello"), Arguments.of("world"));
    }
}

空值参数化

@ParameterizedTest
@NullSource                // 传null
@EmptySource               // 传空字符串/空集合
@NullAndEmptySource        // 传null和空值
@ValueSource(strings = "a")
void testNullable(String s) { ... }