是否可以在 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();
    }
  }