Можно ли отключить параметризованные аргументы тестовой базы в Junit5? - PullRequest
1 голос
/ 13 января 2020

У меня есть сценарий, в котором я пытаюсь отключить параметризованные тесты, но я не хочу отключать их все. Рассмотрим приведенный ниже сценарий макета

@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 до такой степени, что он даже не вызывает отдельные тесты и останавливается на уровне метода.

Редактирование: Как упомянуто Сэмом ниже, это невозможно сделать с помощью стандартного API пока указанные проблемы не будут исправлены / реализованы и выпущены в более новой версии. Однако я смог написать код, используя отражение, чтобы достичь того, чего хотел, поэтому я добавил ответ ниже

Ответы [ 2 ]

1 голос
/ 14 января 2020

Нет, начиная с JUnit Jupiter 5.6 (ожидающего выпуска GA на момент написания этой статьи), нет способа получить доступ к аргументам, использованным для вызова параметризованного теста.

В настоящее время только способ сделать вывод, что этот тип информации действительно, через отображаемое имя.

Следующие открытые проблемы JUnit 5 связаны с этой топи c.

0 голосов
/ 20 января 2020

В настоящее время, до тех пор, пока фактический API не будет реализован в соответствии с проблемами, упомянутыми Сэмом, единственный способ извлечь аргументы - как показано ниже. то есть использование отражения. Это грязный способ для большинства людей, но это единственный способ

Затем, после извлечения аргументов, мы можем манипулировать ими так, как хотим.

@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();
    }
  }
...