【问题标题】:How to test extension implementations如何测试扩展实现
【发布时间】:2017-10-20 01:43:15
【问题描述】:

JUnit 5 API 中有几个可用的扩展点。

例如:

几乎所有这些扩展都采用某种形式的ExtensionContext,它提供对test classtest methodtest instancepublish report entriesstore values 和其他功能的访问。其中很多直接在类实例上操作

大多数实现可能会使用reflection using ReflectionSupportannotation discovery using AnnotationSupport 的某种组合,它们都是静态方法,这使得它们难以模拟。

现在,假设我已经编写了 ExecutionCondition 的实现,或者实现了 BeforeEachCallbackAfterEachCallback 的扩展 - 我如何有效地测试它们?

我想我可以模拟 ExtensionContext,但这似乎不是有效地练习不同代码路径的好方法。

在 JUnit 内部,有 ExecutionEventRecorder,它与 JupiterTestEngine implementation for execution (which is @API(status=INTERNAL)) 一起用于选择和执行测试,然后是 perform assertions on the resulting events

由于JupiterTestEngine 上的public 可见性,我可以使用相同的模式。


这里有几个具体的例子来演示:

  1. 一个ExecutionCondition,它启用基于系统属性的测试。这可以通过一些反射和以@BeforeEach@AfterEach 样式使用TestInfo 进行测试,但是当并行测试执行到来时,处理和可能的问题似乎更复杂。此示例显示了“如何提供真实的ExtensionContext 并在结果上断言”的示例。

    @Target(ElementType.METHOD)
    @Retention(RetentionPolicy.RUNTIME)
    @ExtendWith(SystemPropertyCondition.class)
    public @interface SystemProperty {
      String key();
      String value();
    }
    
    public class SystemPropertyCondition implements ExecutionCondition {
      @Override
      public ConditionEvaluationResult evaluateExecutionCondition(final ExtensionContext context) {
        return context.getTestMethod()
            .flatMap(element -> AnnotationSupport.findAnnotation(element, SystemProperty.class))
            .map(systemProperty -> {
              if (systemProperty.value().equals(System.getProperty(systemProperty.key()))) {
                return ConditionEvaluationResult.enabled("Property is available");
              } else {
                return ConditionEvaluationResult.disabled("Property not equal");
              }
            })
            .orElseGet(() -> ConditionEvaluationResult.enabled("No annotations"));
      }
    }
    
  2. ExecutionCondition 仅在指定的一周中的某一天运行。如何注入测试时钟?如果条件是预期结果,您将如何测试?我猜一些状态/实现可以放在ExtensionContext.Store 中,这将允许在扩展之间传递某种状态(就像BeforeEachCallback 一样,这可能是正确的路径,但这将取决于扩展执行的顺序。我不相信BeforeEachCallbackExecutionCondition 之前被调用,因此该路径可能不是正确的路径。此示例显示“我如何注入依赖项”并显示相同的问题就像前面提供ExtensionContext 并对结果进行断言的示例一样。

    @ExtendWith(RunOnDayCondition.class)
    public @interface RunOnDay {
      DayOfWeek[] value();
    }
    
    final class RunOnDayCondition implements ExecutionCondition {
    
      private static final ConditionEvaluationResult DEFAULT = disabled(
          RunOnDay.class + " is not present"
      );
    
      @Override
      public ConditionEvaluationResult evaluateExecutionCondition(final ExtensionContext context) {
        return context.getElement()
            .flatMap(annotatedElement -> findAnnotation(annotatedElement, RunOnDay.class))
            .map(RunOnDay::value)
            .map(RunOnDayCondition::evaluateIfRunningOnDay)
            .orElse(DEFAULT);
      }
    
      private static ConditionEvaluationResult evaluateIfRunningOnDay(final DayOfWeek[] days) {
        // TODO: How would you inject a test clock?
        final DayOfWeek currentDay = LocalDate.now().getDayOfWeek();
        final boolean runningInday = Stream.of(days).anyMatch(currentDay::equals);
    
        if (runningInday) {
          return enabled("Current day is " + currentDay + ", in the specified days of " + Arrays.toString(days));
        } else {
          return disabled("Current day is " + currentDay + ", not in the specified days of " + Arrays.toString(days));
        }
      }
    }
    
  3. 设置临时目录的扩展,将其作为参数提供,然后在测试后将其清理。这将使用ParameterResolverBeforeEachCallbackAfterEachCallbackExtensionContext.Store。这个例子表明一个扩展实现可以使用多个扩展点,并且可以利用存储来跟踪状态。

用于扩展测试的自定义测试引擎是正确的方法吗?

那么,如何在不依赖内部 API 且不“复制”模拟工作的情况下测试各种扩展实现?

【问题讨论】:

标签: junit5


【解决方案1】:

我知道这不是一个完整的答案(但我现在在移动设备上,您的问题非常复杂)......但是如果 this project 可以帮到你。

如果你限制你的问题,我可以尝试更好地帮助你

【讨论】:

    【解决方案2】:

    JUnit 5.4 起,您可以使用Test Kit 来测试您的扩展。 JUnit 5.7 的功能似乎变得稳定了。 (请注意,这些版本之间的 API 有所不同。)

    使用 Test Kit,您可以在实际测试中执行模拟测试并对结果执行断言。请注意,您可能需要防止直接发现您的 模拟测试Issue #1779 of JUnit 5 可能会帮助你。

    【讨论】:

      猜你喜欢
      • 2011-02-21
      • 1970-01-01
      • 2010-11-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-04-08
      相关资源
      最近更新 更多