junit-team/junit5 · error · ExtensionConfigurationException

The following TestInstanceFactory extensions were registered

Error message

The following TestInstanceFactory extensions were registered for test class [%s], but only one is permitted: %s

What it means

Thrown by ClassBasedTestDescriptor.resolveTestInstanceFactory() during the prepare() phase when the registry contains more than one TestInstanceFactory extension for a single test class. JUnit Jupiter permits at most one TestInstanceFactory per class because two factories would produce ambiguous instances, so the engine fails the entire class up front.

Source

Thrown at junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/ClassBasedTestDescriptor.java:311

		this.testInstanceFactory = null;
	}

	private @Nullable TestInstanceFactory resolveTestInstanceFactory(ExtensionRegistry registry) {
		List<TestInstanceFactory> factories = registry.getExtensions(TestInstanceFactory.class);

		if (factories.size() == 1) {
			return factories.get(0);
		}

		if (factories.size() > 1) {
			String factoryNames = factories.stream()//
					.map(factory -> factory.getClass().getName())//
					.collect(joining(", "));

			String errorMessage = "The following TestInstanceFactory extensions were registered for test class [%s], but only one is permitted: %s".formatted(
				getTestClass().getName(), factoryNames);

			throw new ExtensionConfigurationException(errorMessage);
		}

		return null;
	}

	private TestInstancesProvider testInstancesProvider(JupiterEngineExecutionContext parentExecutionContext,
			ClassExtensionContext ourExtensionContext) {

		// For Lifecycle.PER_CLASS, ourExtensionContext.getTestInstances() is used to store the instance.
		// Otherwise, extensionContext.getTestInstances() is always empty and we always create a new instance.
		return (registry, context) -> ourExtensionContext.getTestInstances().orElseGet(
			() -> instantiateAndPostProcessTestInstance(parentExecutionContext, ourExtensionContext, registry,
				context));
	}

	private TestInstances instantiateAndPostProcessTestInstance(JupiterEngineExecutionContext parentExecutionContext,
			ClassExtensionContext ourExtensionContext, ExtensionRegistry registry,
			JupiterEngineExecutionContext context) {

View on GitHub (pinned to 956246301e)

Solutions

  1. Read the message: it lists the offending factory class names — remove or disable all but one.
  2. If one factory comes from a third-party extension registered via ServiceLoader (META-INF/services/org.junit.jupiter.api.extension.Extension), exclude that class from automatic registration or do not annotate it.
  3. Consolidate instance creation into a single TestInstanceFactory that delegates internally if you need multiple strategies.
  4. Check for @ExtendWith on both a base test class and a subclass pointing at different factory classes.

Example fix

// before — two factories for one class
@ExtendWith(GuiceTestInstanceFactory.class)
class BaseTest {}

@ExtendWith(CustomTestInstanceFactory.class)
class ChildTest extends BaseTest {} // both apply -> ExtensionConfigurationException

// after — single factory, composition handled inside
@ExtendWith(GuiceTestInstanceFactory.class)
class BaseTest {}
class ChildTest extends BaseTest {}
Defensive patterns

Strategy: validation

Validate before calling

// At suite setup, count TestInstanceFactory extensions for the class
List<TestInstanceFactory> factories = new ArrayList<>();
ReflectionUtils.findMethods(...) // or scan @ExtendWith on the class hierarchy
if (factories.size() > 1) throw new IllegalStateException("Duplicate TestInstanceFactory: " + factories);

Prevention

When it happens

Trigger: Registering two TestInstanceFactory implementations for the same class via any combination of @ExtendWith on the class/meta-annotation, @RegisterExtension static fields, programmatic registration via @ExtendsWith on a base class plus a subclass, or a META-INF/services extension auto-registered globally that also implements TestInstanceFactory alongside a locally registered one.

Common situations: Mixing a test-instance-creation framework (e.g. a Mockito/Guice/Spring testinstance factory extension) with a custom factory; upgrading a library that now ships its own TestInstanceFactory that collides with yours; a ServiceLoader-registered extension that auto-applies to all classes while a @RegisterExtension also supplies one.

Related errors


AI-assisted analysis of junit-team/junit5@956246301e (2026-08-04). Data as JSON: /data/errors/5b60d96fb9073921.json. Report an issue: GitHub.