junit-team/junit5 · error · TestInstantiationException
TestInstanceFactory [ ] failed to return an instance of [ ]…
Error message
TestInstanceFactory [%s] failed to return an instance of [%s] and instead returned an instance of [%s].
What it means
Thrown when a TestInstanceFactory returns an object that is not null but is not assignable to the test class. The check uses getTestClass().isInstance(instance); when FQNs collide due to ClassLoader differences, identity hash codes are appended to the names so you can tell the two definitions apart.
Solutions
- Make the factory return ctx.getTestClass().getDeclaredConstructor().newInstance() (or equivalent) so the instance is literally of the test class.
- Resolve ClassLoader conflicts so the test class is loaded exactly once - align the test runtime classpath and remove duplicate classpath entries.
- If the factory must proxy, return a subclass that genuinely extends the test class via ByteBuddy/cglib.
Example fix
// before
@Override
public Object createTestInstance(TestInstanceFactoryContext ctx, ExtensionContext ec) {
return mock(ctx.getTestClass()); // Mockito mock is NOT a test-class instance
}
// after
@Override
public Object createTestInstance(TestInstanceFactoryContext ctx, ExtensionContext ec) {
return ctx.getTestClass().getDeclaredConstructor().newInstance();
} Defensive patterns
Strategy: type-guard
Validate before calling
Object instance = factory.createTestInstance(ctx, extensionContext);
if (instance == null || !ctx.getTestClass().isInstance(instance)) {
throw new IllegalStateException("Factory returned wrong type: " + (instance == null ? "null" : instance.getClass()));
} Type guard
Class<?> testClass = ctx.getTestClass();
// in factory
Object inst = buildInstance();
if (!testClass.isInstance(inst)) {
throw new TestInstantiationException("not a " + testClass.getName() + ": " + inst.getClass());
}
return inst; Prevention
- Have your factory return ctx.getTestClass().getDeclaredConstructor().newInstance() by default.
- Resolve ClassLoader mismatches so the test class is loaded once.
- Avoid returning Mockito mocks or proxies whose Class differs from the test class.
When it happens
Trigger: Factory returns an instance whose Class differs from getTestClass() - returns a subclass loaded by a different loader, returns an unrelated type, or returns a Mockito proxy class whose superclass is not the test class.
Common situations: Test class loaded twice by different ClassLoaders (OSGi, build tools with isolated test classpaths), factory mistakenly returns a wrapper/mock instead of the real test class, or Kotlin companion-object misuse where the factory returns the companion instead of an instance.
Related errors
- TestInstanceFactory [ ] failed to instantiate test class [ ]
- Argument at index [ ] with value [ ] and type [ ] could not…
- Can only resolve @TempDir
- Cannot convert null to primitive value of type
- Could not instantiate TimeZoneProvider because of exception
AI-assisted analysis of junit-team/junit5@f070c699a0 (2026-08-11).
Data as JSON: /api/errors/787d6ec285f255f4.
Report an issue: GitHub.
Appendix: 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 f070c699a0)