junit-team/junit5 · error · TestInstantiationException

TestInstanceFactory [%s] failed to instantiate test class [%

Error message

TestInstanceFactory [%s] failed to instantiate test class [%s]

What it means

Thrown by ClassBasedTestDescriptor.invokeTestInstanceFactory() when a registered TestInstanceFactory.createTestInstance() throws a throwable that is not already a TestInstantiationException. The engine wraps the original exception (appending its message if present) in a TestInstantiationException so that a failure to construct the instance is reported as a test-instantiation failure rather than an arbitrary engine error.

Source

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

		try {
			ExtensionContext actualExtensionContext = extensionContext.get(testInstanceFactory);
			instance = testInstanceFactory.createTestInstance(
				new DefaultTestInstanceFactoryContext(getTestClass(), outerInstance), actualExtensionContext);
		}
		catch (Throwable throwable) {
			UnrecoverableExceptions.rethrowIfUnrecoverable(throwable);

			if (throwable instanceof TestInstantiationException exception) {
				throw exception;
			}

			String message = "TestInstanceFactory [%s] failed to instantiate test class [%s]".formatted(
				testInstanceFactory.getClass().getName(), getTestClass().getName());
			if (StringUtils.isNotBlank(throwable.getMessage())) {
				message += ": " + throwable.getMessage();
			}
			throw new TestInstantiationException(message, throwable);
		}

		if (!getTestClass().isInstance(instance)) {
			String testClassName = getTestClass().getName();
			Class<?> instanceClass = (instance == null ? null : instance.getClass());
			String instanceClassName = (instanceClass == null ? "null" : instanceClass.getName());

			// If the test instance was loaded via a different ClassLoader, append
			// the identity hash codes to the type names to help users disambiguate
			// between otherwise identical "fully qualified class names".
			if (testClassName.equals(instanceClassName)) {
				testClassName += "@" + Integer.toHexString(System.identityHashCode(getTestClass()));
				instanceClassName += "@" + Integer.toHexString(System.identityHashCode(instanceClass));
			}
			String message = "TestInstanceFactory [%s] failed to return an instance of [%s] and instead returned an instance of [%s].".formatted(
				testInstanceFactory.getClass().getName(), testClassName, instanceClassName);

			throw new TestInstantiationException(message);

View on GitHub (pinned to 956246301e)

Solutions

  1. Examine getCause() of the TestInstantiationException — it is the original failure from the factory.
  2. Fix the root cause reported by the factory (e.g. add the missing DI binding, fix constructor accessibility).
  3. If the factory throws intentionally, throw a TestInstantiationException directly so the message is preserved verbatim instead of being wrapped.
  4. Add a unit test for the factory outside JUnit to reproduce instantiation in isolation.

Example fix

// before
public class MyFactory implements TestInstanceFactory {
    public Object createTestInstance(TestInstanceFactoryContext ctx, ExtensionContext ext) {
        return injector.getInstance(ctx.getTestClass()); // throws ConfigurationException -> wrapped
    }
}
// after
public class MyFactory implements TestInstanceFactory {
    public Object createTestInstance(TestInstanceFactoryContext ctx, ExtensionContext ext) {
        try { return injector.getInstance(ctx.getTestClass()); }
        catch (ConfigurationException e) {
            throw new TestInstantiationException("DI failed for " + ctx.getTestClass().getName(), e);
        }
    }
}
Defensive patterns

Strategy: try-catch

Validate before calling

// Validate the factory can build the instance outside JUnit
Object instance;
try { instance = factory.createTestInstance(new DefaultTestInstanceFactoryContext(MyTest.class, null), mockContext); }
catch (Throwable t) { throw new IllegalStateException("Factory cannot build " + MyTest.class, t); }
assert MyTest.class.isInstance(instance);

Try / catch

try {
    // test executes with the factory
} catch (TestInstantiationException e) {
    Throwable root = e.getCause();
    // inspect root for DI/reflective failures and surface them
}

Prevention

When it happens

Trigger: A TestInstanceFactory whose createTestInstance() throws — e.g. a DI container fails to wire the test class, a reflective instantiation hits an inaccessible constructor, or the factory's internal logic throws a RuntimeException.

Common situations: Using a dependency-injection test instance factory where the test class has a missing binding; a factory that calls Class.newInstance() on a class with no no-arg constructor; a factory that queries an external resource during instantiation that is unavailable.

Related errors


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