junit-team/junit5 · error · TestInstantiationException

TestInstanceFactory [%s] failed to return an instance of [%s

Error message

TestInstanceFactory [%s] failed to return an instance of [%s] and instead returned an instance of [%s].

What it means

Thrown by ClassBasedTestDescriptor.invokeTestInstanceFactory() when the factory returns an object that is not an instance of the test class (getTestClass().isInstance(instance) is false). When the returned class name equals the test class name (same FQCN loaded by different ClassLoaders), identity-hash codes are appended to help disambiguate classloader collisions.

Source

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

			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);
		}

		return instance;
	}

	private Object invokeTestClassConstructor(@Nullable Object outerInstance, ExtensionRegistry registry,
			ExtensionContextSupplier extensionContext) {

		Constructor<?> constructor = ReflectionUtils.getDeclaredConstructor(getTestClass());
		return executableInvoker.invoke(constructor, outerInstance, extensionContext, registry,
			InvocationInterceptor::interceptTestClassConstructor);
	}

	private void invokeTestInstancePreConstructCallbacks(TestInstanceFactoryContext factoryContext,
			ExtensionRegistry registry, ExtensionContextSupplier context) {
		registry.stream(TestInstancePreConstructCallback.class).forEach(extension -> executeAndMaskThrowable(
			() -> extension.preConstructTestInstance(factoryContext, context.get(extension))));
	}

View on GitHub (pinned to 956246301e)

Solutions

  1. Make the factory return an instance created from ctx.getTestClass() directly (e.g. getTestClass().getDeclaredConstructor().newInstance()).
  2. If using a proxy/mock, ensure the proxy class extends or implements the test class and is loaded by a ClassLoader consistent with the test.
  3. For ClassLoader collisions, unify the loader so the test class is loaded once; the @identityHashCodes in the message diagnose this case.
  4. Return a non-null value — null is reported as the 'returned an instance of [null]' variant of this same error.

Example fix

// before
public Object createTestInstance(TestInstanceFactoryContext ctx, ExtensionContext ext) {
    return SomeOtherClass.INSTANCE; // wrong type
}
// after
public Object createTestInstance(TestInstanceFactoryContext ctx, ExtensionContext ext) {
    Class<?> c = ctx.getTestClass();
    try { return c.getDeclaredConstructor().newInstance(); }
    catch (Exception e) { throw new TestInstantiationException("fail", e); }
}
Defensive patterns

Strategy: validation

Validate before calling

// In the factory, validate before returning
Object instance = buildInstance(ctx.getTestClass());
if (instance == null || !ctx.getTestClass().isInstance(instance)) {
    throw new TestInstantiationException("Factory returned wrong type: " + (instance == null ? "null" : instance.getClass()));
}
return instance;

Type guard

static boolean factoryReturnsCorrectType(TestInstanceFactory f, Class<?> testClass, ExtensionContext ctx) {
    Object inst = f.createTestInstance(new DefaultTestInstanceFactoryContext(testClass, null), ctx);
    return inst != null && testClass.isInstance(inst);
}

Prevention

When it happens

Trigger: A TestInstanceFactory returns null, returns an instance of a different class, or returns an instance of the right class name loaded by a different ClassLoader than the one JUnit used to discover the test.

Common situations: A mock/proxy factory returning a subclass proxy that is not assignable; OSGi or custom ClassLoader setups where the test class is loaded twice; a factory that returns a shared singleton of a sibling class by mistake; returning a Mockito mock of the class when mocking final classes is disabled (mock is a different generated class).

Related errors


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