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

  1. 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
  2. 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

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


AI-assisted analysis of sebastianbergmann/phpunit@f123cdb2a2 (2026-08-23). Data as JSON: /api/errors/8189907362e29ae4. Report an issue: GitHub.