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) {
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?