junit-team/junit5 · error · ExtensionConfigurationException

The following TestInstanceFactory extensions were…

Error message

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

What it means

Thrown as ExtensionConfigurationException when more than one TestInstanceFactory extension is registered for a single test class. JUnit Jupiter only allows one factory to create the test instance, so the framework refuses to pick arbitrarily and aborts class execution.

Solutions

  1. Inspect the factory names listed in the message to identify the two conflicting factories.
  2. Disable one via the junit.jupiter.execution.extensions.enabled.extension-types filter property (or the deprecated junit.jupiter.extensions.disabled.autodetection) so only the intended factory is active.
  3. Remove the duplicate @ExtendWith / @RegisterEntry / ServiceLoader registration from your test or classpath.
  4. If both are legitimate for different tests, scope them to disjoint classes via @ExtendWith on each rather than globally.

Example fix

// before
@ExtendWith({MockitoExtension.class, MyKotlinFactory.class})
class MyTest { }
// after - whitelist only one factory globally in junit-platform.properties
junit.jupiter.execution.extensions.enabled.extension.types=org.junit.jupiter.api.extension.TestInstanceFactory,com.example.MyKotlinFactory
Defensive patterns

Strategy: validation

Validate before calling

long factoryCount = Stream.of(MyTest.class.getAnnotations())
    .filter(a -> a instanceof ExtendWith)
    .map(a -> ((ExtendWith) a).value())
    .flatMap(Arrays::stream)
    .filter(c -> TestInstanceFactory.class.isAssignableFrom(c))
    .count();
// also scan @RegisterExtension fields/params and ServiceLoader entries
if (factoryCount > 1) throw new IllegalStateException("Multiple TestInstanceFactory registered");

Prevention

When it happens

Trigger: Registering multiple TestInstanceFactory implementations on the same test class - via @RegisterExtension fields/parameters, @ExtendWith meta-annotations, META-INF/services auto-registration, or JupiterConfiguration service-loader entries. The throw site is in ClassBasedTestDescriptor.resolveTestInstanceFactory when factories.size() > 1.

Common situations: Two test libraries both ship a TestInstanceFactory (e.g. a Mockito/Kotest/Testcontainers factory) and both get auto-registered via ServiceLoader; a developer adds @ExtendWith(CustomFactory.class) while a base class already registers another; mixing @RegisterExtension fields of factory type.

Related errors


AI-assisted analysis of junit-team/junit5@f070c699a0 (2026-08-11). Data as JSON: /api/errors/5b60d96fb9073921. Report an issue: GitHub.

Appendix: 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 f070c699a0)