sebastianbergmann/phpunit · error · UnknownClassOrInterfaceException
Class or interface "%s" does not exist
Error message
Class or interface "%s" does not exist
What it means
The IsInstanceOf constraint is constructed with a class or interface name, and its constructor validates immediately that the name refers to an existing class or interface via class_exists()/interface_exists(). If neither exists, this exception is thrown at constraint construction time — before any value is even evaluated.
Source
Thrown at src/Framework/Constraint/Type/IsInstanceOf.php:42
*/
private readonly string $name;
/**
* @var 'class'|'interface'
*/
private readonly string $type;
/**
* @throws UnknownClassOrInterfaceException
*/
public function __construct(string $name)
{
if (class_exists($name)) {
$this->type = 'class';
} elseif (interface_exists($name)) {
$this->type = 'interface';
} else {
throw new UnknownClassOrInterfaceException($name);
}
$this->name = $name;
}
/**
* Returns a string representation of the constraint.
*/
public function toString(): string
{
return sprintf(
'is an instance of %s %s',
$this->type,
$this->name,
);
}
/**View on GitHub (pinned to f123cdb2a2)
Solutions
- Fix the reference: add the missing use statement or correct the fully-qualified name — prefer SomeClass::class over hand-written strings so IDE/refactors catch it
- Run composer dump-autoload / verify the package providing the class is installed (composer show)
Example fix
// before use App\Domain\Userr; // typo / missing import $this->assertInstanceOf(Userr::class, $user); // after use App\Domain\User; $this->assertInstanceOf(User::class, $user);
Defensive patterns
Strategy: validation
Validate before calling
if (!class_exists($className) && !interface_exists($className)) {
$this->markTestSkipped("Unknown class/interface: $className");
}
$this->assertInstanceOf($className, $object); Type guard
function isKnownClassOrInterface(string $name): bool
{
return class_exists($name) || interface_exists($name);
} Prevention
- Always use SomeClass::class instead of string literals in assertInstanceOf()
- Run composer dump-autoload after adding classes; keep test imports tidy with an IDE/lint rule
When it happens
Trigger: assertInstanceOf(SomeClass::class, $object) or createConfiguredMock/isInstanceOf checks where SomeClass is misspelled, not imported (missing use statement), namespaced incorrectly, or lives in an autoloader path not loaded in the test run; also assertInstanceOf('App\Service\UserRepo') with wrong casing/backslashes, or referencing a class from a package that is not installed.
Common situations: Missing `use App\Domain\User;` after copy-pasting a test; refactors that renamed/moved classes while tests still reference old names; running tests before composer dump-autoload; typo in string class names passed dynamically; dev dependencies holding the class not installed in CI.
Related errors
- Class or interface "%s" does not exist
- Event class "%s" does not exist
- Class or interface "%s" does not exist
- Subscriber "%s" does not implement any known interface - did
- Unknown event type "%s"
AI-assisted analysis of sebastianbergmann/phpunit@f123cdb2a2 (2026-08-23).
Data as JSON: /api/errors/8189907362e29ae4.
Report an issue: GitHub.