JUnit 5 Jupiter架构与@ParameterizedTest参数化测试
请详细解释JUnit 5 Jupiter的架构(JUnit Platform + Jupiter + Vintage),以及参数化测试的高级用法。@ParameterizedTest配合@ValueSource/@CsvSource/@MethodSource/@EnumSource等如何实现数据驱动测试?参数化测试中如何自定义参数提供者?
回答
编译有声
JUnit 5三层架构
- JUnit Platform:在JVM上启动测试框架的基础,提供TestEngine API
- JUnit Jupiter:JUnit 5新编程模型的实现(注解+扩展模型)
- 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) { ... }