是否可以在 Junit5 中禁用参数化测试基础参数
Is it possible to disable a Parameterized test basis arguments in Junit5
我有一个场景,我试图禁用参数化测试,但我不想禁用所有这些测试。考虑以下模拟场景
@CsvSource({
"1,1",
"2,2",
"3,not3"
})
@ExtendWith(DisableParameterized.class)
@ParameterizedTest( name = "Test for {0} is equal to {1}")
void equality(String expected, String actual) {
assertEquals(expected, actual, "Not as expected");
}
是否可以编写一个 DisableParameterized implements ExecutionCondition
来禁用基于某些元数据的参数化测试之一。
我能在
中找到关于 ParameterizedTests 的唯一正确信息
public ConditionEvaluationResult evaluateExecutionCondition(ExtensionContext extensionContext)
是displayName
有没有其他方法可以一般性地提供某种元数据来禁用参数化测试?
如果我将它们标记为@Disabled,它会禁用所有 ParameterizedTests 到它甚至不调用单个测试并在方法级别停止的程度。
编辑:
正如下面 Sam 所提到的,在提到的问题是 fixed/implemented 并在更新版本中发布之前,使用标准 API 是不可能的。
然而,我能够使用反射编写代码来实现我想要的,所以我在下面添加了一个答案
不,从 JUnit Jupiter 5.6(在撰写本文时等待 GA 发布)开始,无法访问用于调用参数化测试的参数。
目前,推断此类信息的唯一方法确实是通过显示名称。
以下未解决的 JUnit 5 问题与此主题相关。
目前,在实际API在Sam提到的问题下实现之前,提取参数的唯一方法如下。即使用反射
这对大多数人来说是一种肮脏的方式,但这是唯一的方式
然后在提取参数后,我们可以随意操作它们。
@Override
public ConditionEvaluationResult evaluateExecutionCondition(ExtensionContext context) {
return disableRequiredOnParameterizedTests(context);
}
private ConditionEvaluationResult disableRequiredOnParameterizedTests(ExtensionContext context) {
// See if my custom annotation is present on the test
var onParameters = findRepeatableAnnotation(context, DisableOnParameter.class);
// Or if the test is a Parameterized test after all
// We have access to arguments when the test will be at method level, i.e. MethodExtensionContext
if (!MethodExtensionContext.class.isAssignableFrom(context.getClass())
|| findAnnotations(context, ParameterizedTest.class).isEmpty()
|| onParameters.isEmpty()) {
return enabled("Not set to disable");
}
List<Object> arguments = getArguments(context);
boolean enable = true;
// Do what you want with arguments
.
.
.
return enable ? enabled("Enabling") ? disabled("Disabling");
}
/**
* A blanket exception safe function to extract arguments from Extension context using
* reflection since we don't have direct access to the API
* https://github.com/junit-team/junit5/issues/1139
*
* @param context needs to be of {@link MethodExtensionContext} type since only at that stage
* arguments can be extracted
* @return List of argument objects, empty if any error occurs
*/
private static List<Object> getArguments(ExtensionContext context) {
try {
if(MethodExtensionContext.class.isAssignableFrom(context.getClass())) {
return emptyList();
}
Method method = findMethod(context.getClass(), "getTestDescriptor").orElseThrow();
TestMethodTestDescriptor descriptor =
(TestMethodTestDescriptor) invokeMethod(method, context);
// Get the TestTemplateInvocationContext
Field templateField = descriptor.getClass().getDeclaredField("invocationContext");
templateField.setAccessible(true);
TestTemplateInvocationContext template =
(TestTemplateInvocationContext) templateField.get(descriptor);
// Get the params finally
Field argumentsField = template.getClass().getDeclaredField("arguments");
argumentsField.setAccessible(true);
return asList((Object[]) argumentsField.get(template));
} catch (Throwable ignored) {
return emptyList();
}
}
我有一个场景,我试图禁用参数化测试,但我不想禁用所有这些测试。考虑以下模拟场景
@CsvSource({
"1,1",
"2,2",
"3,not3"
})
@ExtendWith(DisableParameterized.class)
@ParameterizedTest( name = "Test for {0} is equal to {1}")
void equality(String expected, String actual) {
assertEquals(expected, actual, "Not as expected");
}
是否可以编写一个 DisableParameterized implements ExecutionCondition
来禁用基于某些元数据的参数化测试之一。
我能在
中找到关于 ParameterizedTests 的唯一正确信息public ConditionEvaluationResult evaluateExecutionCondition(ExtensionContext extensionContext)
是displayName
有没有其他方法可以一般性地提供某种元数据来禁用参数化测试?
如果我将它们标记为@Disabled,它会禁用所有 ParameterizedTests 到它甚至不调用单个测试并在方法级别停止的程度。
编辑: 正如下面 Sam 所提到的,在提到的问题是 fixed/implemented 并在更新版本中发布之前,使用标准 API 是不可能的。 然而,我能够使用反射编写代码来实现我想要的,所以我在下面添加了一个答案
不,从 JUnit Jupiter 5.6(在撰写本文时等待 GA 发布)开始,无法访问用于调用参数化测试的参数。
目前,推断此类信息的唯一方法确实是通过显示名称。
以下未解决的 JUnit 5 问题与此主题相关。
目前,在实际API在Sam提到的问题下实现之前,提取参数的唯一方法如下。即使用反射 这对大多数人来说是一种肮脏的方式,但这是唯一的方式
然后在提取参数后,我们可以随意操作它们。
@Override
public ConditionEvaluationResult evaluateExecutionCondition(ExtensionContext context) {
return disableRequiredOnParameterizedTests(context);
}
private ConditionEvaluationResult disableRequiredOnParameterizedTests(ExtensionContext context) {
// See if my custom annotation is present on the test
var onParameters = findRepeatableAnnotation(context, DisableOnParameter.class);
// Or if the test is a Parameterized test after all
// We have access to arguments when the test will be at method level, i.e. MethodExtensionContext
if (!MethodExtensionContext.class.isAssignableFrom(context.getClass())
|| findAnnotations(context, ParameterizedTest.class).isEmpty()
|| onParameters.isEmpty()) {
return enabled("Not set to disable");
}
List<Object> arguments = getArguments(context);
boolean enable = true;
// Do what you want with arguments
.
.
.
return enable ? enabled("Enabling") ? disabled("Disabling");
}
/**
* A blanket exception safe function to extract arguments from Extension context using
* reflection since we don't have direct access to the API
* https://github.com/junit-team/junit5/issues/1139
*
* @param context needs to be of {@link MethodExtensionContext} type since only at that stage
* arguments can be extracted
* @return List of argument objects, empty if any error occurs
*/
private static List<Object> getArguments(ExtensionContext context) {
try {
if(MethodExtensionContext.class.isAssignableFrom(context.getClass())) {
return emptyList();
}
Method method = findMethod(context.getClass(), "getTestDescriptor").orElseThrow();
TestMethodTestDescriptor descriptor =
(TestMethodTestDescriptor) invokeMethod(method, context);
// Get the TestTemplateInvocationContext
Field templateField = descriptor.getClass().getDeclaredField("invocationContext");
templateField.setAccessible(true);
TestTemplateInvocationContext template =
(TestTemplateInvocationContext) templateField.get(descriptor);
// Get the params finally
Field argumentsField = template.getClass().getDeclaredField("arguments");
argumentsField.setAccessible(true);
return asList((Object[]) argumentsField.get(template));
} catch (Throwable ignored) {
return emptyList();
}
}