JUnit 5 @ParamterizedTest {arguments} 与 {argumentsWithNames} 占位符

JUnit 5 @ParamterizedTest {arguments} vs {argumentsWithNames} placeholders

我正在使用 JUnit 5.7.0、IntellijIDEA 2021.1.2 CE、MacOS Catalina 10.15。并且不明白两者之间的区别 ParameterizedTest.ARGUMENTS_PLACEHOLDERParameterizedTest.ARGUMENTS_WITH_NAMES_PLACEHOLDER.

根据 javadoc ARGUMENTS_WITH_NAMES_PLACEHOLDER 处理命名参数,而 ARGUMENTS_PLACEHOLDER 只处理参数。 两个测试在 IDEA 中的测试结果看起来是一样的:

import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvSource;

@ParameterizedTest(name = ARGUMENTS_WITH_NAMES_PLACEHOLDER)
@CsvSource({"apple, 1", "banana, 2", "'lemon, lime', 3" })
void testWithArguments(String fruit, int rank) {
}

@ParameterizedTest(name = ARGUMENTS_PLACEHOLDER)
@CsvSource({"apple, 1", "banana, 2", "'lemon, lime', 3" })
void testWithNamedArguments(String fruit, int rank) {
}

任何人都可以提供这两个占位符行为不同的示例吗?

如果你使用 @ParameterizedTest(name = ARGUMENTS_WITH_NAMES_PLACEHOLDER) 你会得到 parameterName + "=" + paraveterValue.

的输出结果

但是如果你使用 @ParameterizedTest(name = ARGUMENTS_PLACEHOLDER) 你只会得到 paraveterValue

此外,您可以在 javadoc 中看到:

Placeholder for the complete, comma-separated named arguments list of the current invocation of a @ParameterizedTest method: {argumentsWithNames}

@API(status = EXPERIMENTAL, since = "5.6")
String ARGUMENTS_WITH_NAMES_PLACEHOLDER = "{argumentsWithNames}";

Default display name pattern for the current invocation of a @ParameterizedTest method: "[{index}] {argumentsWithNames}"
Note that the default pattern does not include the display name of the @ParameterizedTest method.

@API(status = EXPERIMENTAL, since = "5.3")
String DEFAULT_DISPLAY_NAME = "[" + INDEX_PLACEHOLDER + "] " + ARGUMENTS_WITH_NAMES_PLACEHOLDER;

我试过 运行 你的代码是这样的:

@ParameterizedTest(name = ARGUMENTS_WITH_NAMES_PLACEHOLDER)
@CsvSource({"apple, 1", "banana, 2", "'lemon, lime', 3" })
void testWithNamedArguments(String fruit, int rank) {
}

我得到了正确的结果:

我用的是jupiter 5.6.3,这个功能ARGUMENTS_WITH_NAMES_PLACEHOLDER是从5.6版本开始出现的

解决方案

ARGUMENTS_WITH_NAMES_PLACEHOLDER按预期工作,必须使用
编译测试 -parameters 标志。然后,参数名称将被 1) 存储,并且 2) 随后能够由 JUnit 通过反射检索。

实践中

对于使用 Gradle 构建的 Java 项目,以下将启用此标志专门用于测试:

tasks.named('compileTestJava') {
    options.compilerArgs += '-parameters'
}

参考

  • Java 8 documentationjavac:

    -parameters Stores formal parameter names of constructors and methods in the generated class file so that the method java.lang.reflect.Executable.getParameters from the Reflection API can retrieve them.

  • 自然地,JUnit 使用反射来获取参数名称。例如,查看 ParameterizedTestMethodContext#getParameterName(来自 v5.7.1 的示例)。