How to test extensions

The JUnit 5 API has several extension points.

For instance:

Almost all of these extensions are in the form ExtensionContext, which provides access to the test class , test method , test instance , the ability to publish a report recording , save the values and other features. Many of them work directly on class instances.

Most implementations are likely to use some combination of reflection usingReflectionSupport and usingAnnotationSupport , which are static methods, making it difficult to falsify them.

, , ExecutionCondition , BeforeEachCallback, AfterEachCallback - ?

, ExtensionContext, .

JUnit ExecutionEventRecorder, JupiterTestEngine ( @API(status=INTERNAL)) , .

- public JupiterTestEngine.


:

  • An ExecutionCondition, . TestInfo @BeforeEach @AfterEach, . " 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"));
      }
    }
    
  • An ExecutionCondition, . ? , ? , / ExtensionContext.Store, - (, BeforeEachCallback, , . , BeforeEachCallback ExecutionCondition, 1. " ", , 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));
        }
      }
    }
    
  • , , , . ParameterResolver, BeforeEachCallback, AfterEachCallback ExtensionContext.Store. , .

?

, API "" mocks?

+2
1

, ( , )... , , .

,

0

Source: https://habr.com/ru/post/1689116/


All Articles