Skip to content

Commit

Permalink
Fix programmatic extension registration for nested classes
Browse files Browse the repository at this point in the history
Prior to this commit, extensions registered programmatically using the
`RegisterExtension` annotation were added to the wrong extension
registry multiple times for nested classes and their descendants.
Instead of storing them in the registry on the same level as the test
instance, they were always stored in the registry of the enclosing
class.

`TestInstancesProvider` now takes two arguments: An unmodifiable
`ExtensionRegistry` that is used to instantiate and initialize the test
instance and an extension registrar that is used to register additional
extensions that are registered programmatically. Except for nested
classes these are always the same. For nested classes, we need to
ensure that extensions registered on their level and below are not used
to initialize enclosing classes. Thus, the parent's registry is used
for initialization but additional extensions from fields of the class
are registered with the current registry (usually the registry of the
test method, unless Lifecycle.PER_CLASS is used).

Fixes #1925.
  • Loading branch information
marcphilipp committed Jun 19, 2019
1 parent c281338 commit 932ff16
Show file tree
Hide file tree
Showing 18 changed files with 383 additions and 262 deletions.
Expand Up @@ -54,7 +54,9 @@
import org.junit.jupiter.engine.execution.ExecutableInvoker.ReflectiveInterceptorCall.VoidMethodInterceptorCall; import org.junit.jupiter.engine.execution.ExecutableInvoker.ReflectiveInterceptorCall.VoidMethodInterceptorCall;
import org.junit.jupiter.engine.execution.JupiterEngineExecutionContext; import org.junit.jupiter.engine.execution.JupiterEngineExecutionContext;
import org.junit.jupiter.engine.execution.TestInstancesProvider; import org.junit.jupiter.engine.execution.TestInstancesProvider;
import org.junit.jupiter.engine.extension.ExtensionRegistrar;
import org.junit.jupiter.engine.extension.ExtensionRegistry; import org.junit.jupiter.engine.extension.ExtensionRegistry;
import org.junit.jupiter.engine.extension.MutableExtensionRegistry;
import org.junit.platform.commons.JUnitException; import org.junit.platform.commons.JUnitException;
import org.junit.platform.commons.util.BlacklistedExceptions; import org.junit.platform.commons.util.BlacklistedExceptions;
import org.junit.platform.commons.util.ExceptionUtils; import org.junit.platform.commons.util.ExceptionUtils;
Expand Down Expand Up @@ -135,7 +137,7 @@ public Set<ExclusiveResource> getExclusiveResources() {


@Override @Override
public JupiterEngineExecutionContext prepare(JupiterEngineExecutionContext context) { public JupiterEngineExecutionContext prepare(JupiterEngineExecutionContext context) {
ExtensionRegistry registry = populateNewExtensionRegistryFromExtendWithAnnotation( MutableExtensionRegistry registry = populateNewExtensionRegistryFromExtendWithAnnotation(
context.getExtensionRegistry(), this.testClass); context.getExtensionRegistry(), this.testClass);


// Register extensions from static fields here, at the class level but // Register extensions from static fields here, at the class level but
Expand All @@ -159,7 +161,7 @@ public JupiterEngineExecutionContext prepare(JupiterEngineExecutionContext conte


// @formatter:off // @formatter:off
return context.extend() return context.extend()
.withTestInstancesProvider(testInstancesProvider(context, registry, extensionContext)) .withTestInstancesProvider(testInstancesProvider(context, extensionContext))
.withExtensionRegistry(registry) .withExtensionRegistry(registry)
.withExtensionContext(extensionContext) .withExtensionContext(extensionContext)
.withThrowableCollector(throwableCollector) .withThrowableCollector(throwableCollector)
Expand All @@ -177,7 +179,7 @@ public JupiterEngineExecutionContext before(JupiterEngineExecutionContext contex
// and store the instance in the ExtensionContext. // and store the instance in the ExtensionContext.
ClassExtensionContext extensionContext = (ClassExtensionContext) context.getExtensionContext(); ClassExtensionContext extensionContext = (ClassExtensionContext) context.getExtensionContext();
throwableCollector.execute(() -> extensionContext.setTestInstances( throwableCollector.execute(() -> extensionContext.setTestInstances(
context.getTestInstancesProvider().getTestInstances(Optional.empty()))); context.getTestInstancesProvider().getTestInstances(context.getExtensionRegistry())));
} }


if (throwableCollector.isEmpty()) { if (throwableCollector.isEmpty()) {
Expand Down Expand Up @@ -242,29 +244,26 @@ private TestInstanceFactory resolveTestInstanceFactory(ExtensionRegistry registr
} }


private TestInstancesProvider testInstancesProvider(JupiterEngineExecutionContext parentExecutionContext, private TestInstancesProvider testInstancesProvider(JupiterEngineExecutionContext parentExecutionContext,
ExtensionRegistry registry, ClassExtensionContext extensionContext) { ClassExtensionContext extensionContext) {


TestInstancesProvider testInstancesProvider = childRegistry -> instantiateAndPostProcessTestInstance( return (registry, registrar) -> extensionContext.getTestInstances().orElseGet(
parentExecutionContext, extensionContext, childRegistry.orElse(registry)); () -> instantiateAndPostProcessTestInstance(parentExecutionContext, extensionContext, registry, registrar));

return childRegistry -> extensionContext.getTestInstances().orElseGet(
() -> testInstancesProvider.getTestInstances(childRegistry));
} }


private TestInstances instantiateAndPostProcessTestInstance(JupiterEngineExecutionContext parentExecutionContext, private TestInstances instantiateAndPostProcessTestInstance(JupiterEngineExecutionContext parentExecutionContext,
ExtensionContext extensionContext, ExtensionRegistry registry) { ExtensionContext extensionContext, ExtensionRegistry registry, ExtensionRegistrar registrar) {


TestInstances instances = instantiateTestClass(parentExecutionContext, registry, extensionContext); TestInstances instances = instantiateTestClass(parentExecutionContext, registry, registrar, extensionContext);
invokeTestInstancePostProcessors(instances.getInnermostInstance(), registry, extensionContext); invokeTestInstancePostProcessors(instances.getInnermostInstance(), registry, extensionContext);
// In addition, we register extensions from instance fields here since the // In addition, we register extensions from instance fields here since the
// best time to do that is immediately following test class instantiation // best time to do that is immediately following test class instantiation
// and post processing. // and post processing.
registerExtensionsFromFields(registry, this.testClass, instances.getInnermostInstance()); registerExtensionsFromFields(registrar, this.testClass, instances.getInnermostInstance());
return instances; return instances;
} }


protected abstract TestInstances instantiateTestClass(JupiterEngineExecutionContext parentExecutionContext, protected abstract TestInstances instantiateTestClass(JupiterEngineExecutionContext parentExecutionContext,
ExtensionRegistry registry, ExtensionContext extensionContext); ExtensionRegistry registry, ExtensionRegistrar registrar, ExtensionContext extensionContext);


protected TestInstances instantiateTestClass(Optional<TestInstances> outerInstances, ExtensionRegistry registry, protected TestInstances instantiateTestClass(Optional<TestInstances> outerInstances, ExtensionRegistry registry,
ExtensionContext extensionContext) { ExtensionContext extensionContext) {
Expand Down Expand Up @@ -420,12 +419,12 @@ private void invokeAfterAllCallbacks(JupiterEngineExecutionContext context) {
.forEach(extension -> throwableCollector.execute(() -> extension.afterAll(extensionContext))); .forEach(extension -> throwableCollector.execute(() -> extension.afterAll(extensionContext)));
} }


private void registerBeforeEachMethodAdapters(ExtensionRegistry registry) { private void registerBeforeEachMethodAdapters(ExtensionRegistrar registrar) {
List<Method> beforeEachMethods = findBeforeEachMethods(this.testClass); List<Method> beforeEachMethods = findBeforeEachMethods(this.testClass);
registerMethodsAsExtensions(beforeEachMethods, registry, this::synthesizeBeforeEachMethodAdapter); registerMethodsAsExtensions(beforeEachMethods, registrar, this::synthesizeBeforeEachMethodAdapter);
} }


private void registerAfterEachMethodAdapters(ExtensionRegistry registry) { private void registerAfterEachMethodAdapters(ExtensionRegistrar registrar) {
// Make a local copy since findAfterEachMethods() returns an immutable list. // Make a local copy since findAfterEachMethods() returns an immutable list.
List<Method> afterEachMethods = new ArrayList<>(findAfterEachMethods(this.testClass)); List<Method> afterEachMethods = new ArrayList<>(findAfterEachMethods(this.testClass));


Expand All @@ -435,13 +434,13 @@ private void registerAfterEachMethodAdapters(ExtensionRegistry registry) {
// we register them as synthesized extensions. // we register them as synthesized extensions.
Collections.reverse(afterEachMethods); Collections.reverse(afterEachMethods);


registerMethodsAsExtensions(afterEachMethods, registry, this::synthesizeAfterEachMethodAdapter); registerMethodsAsExtensions(afterEachMethods, registrar, this::synthesizeAfterEachMethodAdapter);
} }


private void registerMethodsAsExtensions(List<Method> methods, ExtensionRegistry registry, private void registerMethodsAsExtensions(List<Method> methods, ExtensionRegistrar registrar,
Function<Method, Extension> extensionSynthesizer) { Function<Method, Extension> extensionSynthesizer) {


methods.forEach(method -> registry.registerExtension(extensionSynthesizer.apply(method), method)); methods.forEach(method -> registrar.registerExtension(extensionSynthesizer.apply(method), method));
} }


private BeforeEachMethodAdapter synthesizeBeforeEachMethodAdapter(Method method) { private BeforeEachMethodAdapter synthesizeBeforeEachMethodAdapter(Method method) {
Expand Down
Expand Up @@ -22,6 +22,7 @@
import org.junit.jupiter.api.extension.TestInstances; import org.junit.jupiter.api.extension.TestInstances;
import org.junit.jupiter.engine.config.JupiterConfiguration; import org.junit.jupiter.engine.config.JupiterConfiguration;
import org.junit.jupiter.engine.execution.JupiterEngineExecutionContext; import org.junit.jupiter.engine.execution.JupiterEngineExecutionContext;
import org.junit.jupiter.engine.extension.ExtensionRegistrar;
import org.junit.jupiter.engine.extension.ExtensionRegistry; import org.junit.jupiter.engine.extension.ExtensionRegistry;
import org.junit.platform.engine.TestDescriptor; import org.junit.platform.engine.TestDescriptor;
import org.junit.platform.engine.TestTag; import org.junit.platform.engine.TestTag;
Expand Down Expand Up @@ -65,7 +66,7 @@ public ExecutionMode getExecutionMode() {


@Override @Override
protected TestInstances instantiateTestClass(JupiterEngineExecutionContext parentExecutionContext, protected TestInstances instantiateTestClass(JupiterEngineExecutionContext parentExecutionContext,
ExtensionRegistry registry, ExtensionContext extensionContext) { ExtensionRegistry registry, ExtensionRegistrar registrar, ExtensionContext extensionContext) {
return instantiateTestClass(Optional.empty(), registry, extensionContext); return instantiateTestClass(Optional.empty(), registry, extensionContext);
} }


Expand Down
Expand Up @@ -29,15 +29,17 @@
import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.api.extension.ExtendWith;
import org.junit.jupiter.api.extension.Extension; import org.junit.jupiter.api.extension.Extension;
import org.junit.jupiter.api.extension.RegisterExtension; import org.junit.jupiter.api.extension.RegisterExtension;
import org.junit.jupiter.engine.extension.ExtensionRegistry; import org.junit.jupiter.engine.extension.ExtensionRegistrar;
import org.junit.jupiter.engine.extension.MutableExtensionRegistry;
import org.junit.platform.commons.util.Preconditions; import org.junit.platform.commons.util.Preconditions;
import org.junit.platform.commons.util.ReflectionUtils; import org.junit.platform.commons.util.ReflectionUtils;


/** /**
* Collection of utilities for working with extensions and the extension registry. * Collection of utilities for working with extensions and the extension registry.
* *
* @since 5.1 * @since 5.1
* @see ExtensionRegistry * @see ExtensionRegistrar
* @see MutableExtensionRegistry
* @see ExtendWith * @see ExtendWith
* @see RegisterExtension * @see RegisterExtension
*/ */
Expand All @@ -48,7 +50,7 @@ private ExtensionUtils() {
} }


/** /**
* Populate a new {@link ExtensionRegistry} from extension types declared via * Populate a new {@link MutableExtensionRegistry} from extension types declared via
* {@link ExtendWith @ExtendWith} on the supplied {@link AnnotatedElement}. * {@link ExtendWith @ExtendWith} on the supplied {@link AnnotatedElement}.
* *
* @param parentRegistry the parent extension registry to set in the newly * @param parentRegistry the parent extension registry to set in the newly
Expand All @@ -59,8 +61,8 @@ private ExtensionUtils() {
* @return the new extension registry; never {@code null} * @return the new extension registry; never {@code null}
* @since 5.0 * @since 5.0
*/ */
static ExtensionRegistry populateNewExtensionRegistryFromExtendWithAnnotation(ExtensionRegistry parentRegistry, static MutableExtensionRegistry populateNewExtensionRegistryFromExtendWithAnnotation(
AnnotatedElement annotatedElement) { MutableExtensionRegistry parentRegistry, AnnotatedElement annotatedElement) {


Preconditions.notNull(parentRegistry, "Parent ExtensionRegistry must not be null"); Preconditions.notNull(parentRegistry, "Parent ExtensionRegistry must not be null");
Preconditions.notNull(annotatedElement, "AnnotatedElement must not be null"); Preconditions.notNull(annotatedElement, "AnnotatedElement must not be null");
Expand All @@ -72,7 +74,7 @@ static ExtensionRegistry populateNewExtensionRegistryFromExtendWithAnnotation(Ex
.collect(toList()); .collect(toList());
// @formatter:on // @formatter:on


return ExtensionRegistry.createRegistryFrom(parentRegistry, extensionTypes); return MutableExtensionRegistry.createRegistryFrom(parentRegistry, extensionTypes);
} }


/** /**
Expand All @@ -82,13 +84,13 @@ static ExtensionRegistry populateNewExtensionRegistryFromExtendWithAnnotation(Ex
* <p>The extensions will be sorted according to {@link Order @Order} semantics * <p>The extensions will be sorted according to {@link Order @Order} semantics
* prior to registration. * prior to registration.
* *
* @param registry the registry in which to register the extensions; never {@code null} * @param registrar the registrar with which to register the extensions; never {@code null}
* @param clazz the class or interface in which to find the fields; never {@code null} * @param clazz the class or interface in which to find the fields; never {@code null}
* @param instance the instance of the supplied class; may be {@code null} * @param instance the instance of the supplied class; may be {@code null}
* when searching for {@code static} fields in the class * when searching for {@code static} fields in the class
*/ */
static void registerExtensionsFromFields(ExtensionRegistry registry, Class<?> clazz, Object instance) { static void registerExtensionsFromFields(ExtensionRegistrar registrar, Class<?> clazz, Object instance) {
Preconditions.notNull(registry, "ExtensionRegistry must not be null"); Preconditions.notNull(registrar, "ExtensionRegistrar must not be null");
Preconditions.notNull(clazz, "Class must not be null"); Preconditions.notNull(clazz, "Class must not be null");


Predicate<Field> predicate = (instance == null ? ReflectionUtils::isStatic : ReflectionUtils::isNotStatic); Predicate<Field> predicate = (instance == null ? ReflectionUtils::isStatic : ReflectionUtils::isNotStatic);
Expand All @@ -108,7 +110,7 @@ static void registerExtensionsFromFields(ExtensionRegistry registry, Class<?> cl
Preconditions.condition(value instanceof Extension, () -> String.format( Preconditions.condition(value instanceof Extension, () -> String.format(
"Failed to register extension via @RegisterExtension field [%s]: field value's type [%s] must implement an [%s] API.", "Failed to register extension via @RegisterExtension field [%s]: field value's type [%s] must implement an [%s] API.",
field, (value != null ? value.getClass().getName() : null), Extension.class.getName())); field, (value != null ? value.getClass().getName() : null), Extension.class.getName()));
registry.registerExtension((Extension) value, field); registrar.registerExtension((Extension) value, field);
}); });
}); });
} }
Expand Down
Expand Up @@ -12,13 +12,12 @@


import static org.apiguardian.api.API.Status.INTERNAL; import static org.apiguardian.api.API.Status.INTERNAL;
import static org.junit.jupiter.engine.descriptor.JupiterTestDescriptor.toExecutionMode; import static org.junit.jupiter.engine.descriptor.JupiterTestDescriptor.toExecutionMode;
import static org.junit.jupiter.engine.extension.ExtensionRegistry.createRegistryWithDefaultExtensions;


import org.apiguardian.api.API; import org.apiguardian.api.API;
import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.jupiter.api.extension.ExtensionContext;
import org.junit.jupiter.engine.config.JupiterConfiguration; import org.junit.jupiter.engine.config.JupiterConfiguration;
import org.junit.jupiter.engine.execution.JupiterEngineExecutionContext; import org.junit.jupiter.engine.execution.JupiterEngineExecutionContext;
import org.junit.jupiter.engine.extension.ExtensionRegistry; import org.junit.jupiter.engine.extension.MutableExtensionRegistry;
import org.junit.platform.engine.EngineExecutionListener; import org.junit.platform.engine.EngineExecutionListener;
import org.junit.platform.engine.UniqueId; import org.junit.platform.engine.UniqueId;
import org.junit.platform.engine.support.descriptor.EngineDescriptor; import org.junit.platform.engine.support.descriptor.EngineDescriptor;
Expand Down Expand Up @@ -49,7 +48,8 @@ public ExecutionMode getExecutionMode() {


@Override @Override
public JupiterEngineExecutionContext prepare(JupiterEngineExecutionContext context) { public JupiterEngineExecutionContext prepare(JupiterEngineExecutionContext context) {
ExtensionRegistry extensionRegistry = createRegistryWithDefaultExtensions(context.getConfiguration()); MutableExtensionRegistry extensionRegistry = MutableExtensionRegistry.createRegistryWithDefaultExtensions(
context.getConfiguration());
EngineExecutionListener executionListener = context.getExecutionListener(); EngineExecutionListener executionListener = context.getExecutionListener();
ExtensionContext extensionContext = new JupiterEngineExtensionContext(executionListener, this, ExtensionContext extensionContext = new JupiterEngineExtensionContext(executionListener, this,
context.getConfiguration()); context.getConfiguration());
Expand Down
Expand Up @@ -22,6 +22,7 @@
import org.junit.jupiter.api.extension.TestInstances; import org.junit.jupiter.api.extension.TestInstances;
import org.junit.jupiter.engine.config.JupiterConfiguration; import org.junit.jupiter.engine.config.JupiterConfiguration;
import org.junit.jupiter.engine.execution.JupiterEngineExecutionContext; import org.junit.jupiter.engine.execution.JupiterEngineExecutionContext;
import org.junit.jupiter.engine.extension.ExtensionRegistrar;
import org.junit.jupiter.engine.extension.ExtensionRegistry; import org.junit.jupiter.engine.extension.ExtensionRegistry;
import org.junit.platform.engine.TestDescriptor; import org.junit.platform.engine.TestDescriptor;
import org.junit.platform.engine.TestTag; import org.junit.platform.engine.TestTag;
Expand Down Expand Up @@ -60,12 +61,12 @@ public final Set<TestTag> getTags() {


@Override @Override
protected TestInstances instantiateTestClass(JupiterEngineExecutionContext parentExecutionContext, protected TestInstances instantiateTestClass(JupiterEngineExecutionContext parentExecutionContext,
ExtensionRegistry registry, ExtensionContext extensionContext) { ExtensionRegistry registry, ExtensionRegistrar registrar, ExtensionContext extensionContext) {


// Extensions registered for nested classes and below are not to be used for instantiating outer classes // Extensions registered for nested classes and below are not to be used for instantiating and initializing outer classes
Optional<ExtensionRegistry> childExtensionRegistryForOuterInstance = Optional.empty(); ExtensionRegistry extensionRegistryForOuterInstanceCreation = parentExecutionContext.getExtensionRegistry();
TestInstances outerInstances = parentExecutionContext.getTestInstancesProvider().getTestInstances( TestInstances outerInstances = parentExecutionContext.getTestInstancesProvider().getTestInstances(
childExtensionRegistryForOuterInstance); extensionRegistryForOuterInstanceCreation, registrar);
return instantiateTestClass(Optional.of(outerInstances), registry, extensionContext); return instantiateTestClass(Optional.of(outerInstances), registry, extensionContext);
} }


Expand Down
Expand Up @@ -38,6 +38,7 @@
import org.junit.jupiter.engine.execution.ExecutableInvoker.ReflectiveInterceptorCall; import org.junit.jupiter.engine.execution.ExecutableInvoker.ReflectiveInterceptorCall;
import org.junit.jupiter.engine.execution.JupiterEngineExecutionContext; import org.junit.jupiter.engine.execution.JupiterEngineExecutionContext;
import org.junit.jupiter.engine.extension.ExtensionRegistry; import org.junit.jupiter.engine.extension.ExtensionRegistry;
import org.junit.jupiter.engine.extension.MutableExtensionRegistry;
import org.junit.platform.commons.logging.Logger; import org.junit.platform.commons.logging.Logger;
import org.junit.platform.commons.logging.LoggerFactory; import org.junit.platform.commons.logging.LoggerFactory;
import org.junit.platform.commons.util.BlacklistedExceptions; import org.junit.platform.commons.util.BlacklistedExceptions;
Expand Down Expand Up @@ -96,13 +97,13 @@ public Type getType() {
// --- Node ---------------------------------------------------------------- // --- Node ----------------------------------------------------------------


@Override @Override
public JupiterEngineExecutionContext prepare(JupiterEngineExecutionContext context) throws Exception { public JupiterEngineExecutionContext prepare(JupiterEngineExecutionContext context) {
ExtensionRegistry registry = populateNewExtensionRegistry(context); MutableExtensionRegistry registry = populateNewExtensionRegistry(context);
ThrowableCollector throwableCollector = createThrowableCollector(); ThrowableCollector throwableCollector = createThrowableCollector();
MethodExtensionContext extensionContext = new MethodExtensionContext(context.getExtensionContext(), MethodExtensionContext extensionContext = new MethodExtensionContext(context.getExtensionContext(),
context.getExecutionListener(), this, context.getConfiguration(), throwableCollector); context.getExecutionListener(), this, context.getConfiguration(), throwableCollector);
throwableCollector.execute(() -> { throwableCollector.execute(() -> {
TestInstances testInstances = context.getTestInstancesProvider().getTestInstances(Optional.of(registry)); TestInstances testInstances = context.getTestInstancesProvider().getTestInstances(registry);
extensionContext.setTestInstances(testInstances); extensionContext.setTestInstances(testInstances);
}); });


Expand All @@ -115,7 +116,7 @@ public JupiterEngineExecutionContext prepare(JupiterEngineExecutionContext conte
// @formatter:on // @formatter:on
} }


protected ExtensionRegistry populateNewExtensionRegistry(JupiterEngineExecutionContext context) { protected MutableExtensionRegistry populateNewExtensionRegistry(JupiterEngineExecutionContext context) {
return populateNewExtensionRegistryFromExtendWithAnnotation(context.getExtensionRegistry(), getTestMethod()); return populateNewExtensionRegistryFromExtendWithAnnotation(context.getExtensionRegistry(), getTestMethod());
} }


Expand Down
Expand Up @@ -22,7 +22,7 @@
import org.junit.jupiter.engine.config.JupiterConfiguration; import org.junit.jupiter.engine.config.JupiterConfiguration;
import org.junit.jupiter.engine.execution.ExecutableInvoker.ReflectiveInterceptorCall; import org.junit.jupiter.engine.execution.ExecutableInvoker.ReflectiveInterceptorCall;
import org.junit.jupiter.engine.execution.JupiterEngineExecutionContext; import org.junit.jupiter.engine.execution.JupiterEngineExecutionContext;
import org.junit.jupiter.engine.extension.ExtensionRegistry; import org.junit.jupiter.engine.extension.MutableExtensionRegistry;
import org.junit.platform.engine.TestDescriptor; import org.junit.platform.engine.TestDescriptor;
import org.junit.platform.engine.UniqueId; import org.junit.platform.engine.UniqueId;
import org.junit.platform.engine.support.hierarchical.ExclusiveResource; import org.junit.platform.engine.support.hierarchical.ExclusiveResource;
Expand Down Expand Up @@ -63,8 +63,8 @@ public String getLegacyReportingName() {
} }


@Override @Override
protected ExtensionRegistry populateNewExtensionRegistry(JupiterEngineExecutionContext context) { protected MutableExtensionRegistry populateNewExtensionRegistry(JupiterEngineExecutionContext context) {
ExtensionRegistry registry = super.populateNewExtensionRegistry(context); MutableExtensionRegistry registry = super.populateNewExtensionRegistry(context);
invocationContext.getAdditionalExtensions().forEach( invocationContext.getAdditionalExtensions().forEach(
extension -> registry.registerExtension(extension, invocationContext)); extension -> registry.registerExtension(extension, invocationContext));
return registry; return registry;
Expand Down
Expand Up @@ -27,6 +27,7 @@
import org.junit.jupiter.engine.config.JupiterConfiguration; import org.junit.jupiter.engine.config.JupiterConfiguration;
import org.junit.jupiter.engine.execution.JupiterEngineExecutionContext; import org.junit.jupiter.engine.execution.JupiterEngineExecutionContext;
import org.junit.jupiter.engine.extension.ExtensionRegistry; import org.junit.jupiter.engine.extension.ExtensionRegistry;
import org.junit.jupiter.engine.extension.MutableExtensionRegistry;
import org.junit.platform.commons.util.Preconditions; import org.junit.platform.commons.util.Preconditions;
import org.junit.platform.engine.TestDescriptor; import org.junit.platform.engine.TestDescriptor;
import org.junit.platform.engine.UniqueId; import org.junit.platform.engine.UniqueId;
Expand Down Expand Up @@ -71,7 +72,7 @@ public boolean mayRegisterTests() {


@Override @Override
public JupiterEngineExecutionContext prepare(JupiterEngineExecutionContext context) throws Exception { public JupiterEngineExecutionContext prepare(JupiterEngineExecutionContext context) throws Exception {
ExtensionRegistry registry = populateNewExtensionRegistryFromExtendWithAnnotation( MutableExtensionRegistry registry = populateNewExtensionRegistryFromExtendWithAnnotation(
context.getExtensionRegistry(), getTestMethod()); context.getExtensionRegistry(), getTestMethod());


// The test instance should be properly maintained by the enclosing class's ExtensionContext. // The test instance should be properly maintained by the enclosing class's ExtensionContext.
Expand Down
Expand Up @@ -15,7 +15,7 @@
import org.apiguardian.api.API; import org.apiguardian.api.API;
import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.jupiter.api.extension.ExtensionContext;
import org.junit.jupiter.engine.config.JupiterConfiguration; import org.junit.jupiter.engine.config.JupiterConfiguration;
import org.junit.jupiter.engine.extension.ExtensionRegistry; import org.junit.jupiter.engine.extension.MutableExtensionRegistry;
import org.junit.platform.commons.JUnitException; import org.junit.platform.commons.JUnitException;
import org.junit.platform.commons.logging.Logger; import org.junit.platform.commons.logging.Logger;
import org.junit.platform.commons.logging.LoggerFactory; import org.junit.platform.commons.logging.LoggerFactory;
Expand Down Expand Up @@ -71,7 +71,7 @@ public TestInstancesProvider getTestInstancesProvider() {
return this.state.testInstancesProvider; return this.state.testInstancesProvider;
} }


public ExtensionRegistry getExtensionRegistry() { public MutableExtensionRegistry getExtensionRegistry() {
return this.state.extensionRegistry; return this.state.extensionRegistry;
} }


Expand Down Expand Up @@ -125,7 +125,7 @@ private static final class State implements Cloneable {
final EngineExecutionListener executionListener; final EngineExecutionListener executionListener;
final JupiterConfiguration configuration; final JupiterConfiguration configuration;
TestInstancesProvider testInstancesProvider; TestInstancesProvider testInstancesProvider;
ExtensionRegistry extensionRegistry; MutableExtensionRegistry extensionRegistry;
ExtensionContext extensionContext; ExtensionContext extensionContext;
ThrowableCollector throwableCollector; ThrowableCollector throwableCollector;


Expand Down Expand Up @@ -160,7 +160,7 @@ public Builder withTestInstancesProvider(TestInstancesProvider testInstancesProv
return this; return this;
} }


public Builder withExtensionRegistry(ExtensionRegistry extensionRegistry) { public Builder withExtensionRegistry(MutableExtensionRegistry extensionRegistry) {
newState().extensionRegistry = extensionRegistry; newState().extensionRegistry = extensionRegistry;
return this; return this;
} }
Expand Down
Expand Up @@ -12,11 +12,11 @@


import static org.apiguardian.api.API.Status.INTERNAL; import static org.apiguardian.api.API.Status.INTERNAL;


import java.util.Optional;

import org.apiguardian.api.API; import org.apiguardian.api.API;
import org.junit.jupiter.api.extension.TestInstances; import org.junit.jupiter.api.extension.TestInstances;
import org.junit.jupiter.engine.extension.ExtensionRegistrar;
import org.junit.jupiter.engine.extension.ExtensionRegistry; import org.junit.jupiter.engine.extension.ExtensionRegistry;
import org.junit.jupiter.engine.extension.MutableExtensionRegistry;


/** /**
* @since 5.0 * @since 5.0
Expand All @@ -25,6 +25,10 @@
@API(status = INTERNAL, since = "5.0") @API(status = INTERNAL, since = "5.0")
public interface TestInstancesProvider { public interface TestInstancesProvider {


TestInstances getTestInstances(Optional<ExtensionRegistry> childExtensionRegistry); default TestInstances getTestInstances(MutableExtensionRegistry extensionRegistry) {
return getTestInstances(extensionRegistry, extensionRegistry);
}

TestInstances getTestInstances(ExtensionRegistry extensionRegistry, ExtensionRegistrar extensionRegistrar);


} }

1 comment on commit 932ff16

@sbrannen
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

Please sign in to comment.