{"record":{"id":"5604568a439b2a68","repo":"sebastianbergmann/phpunit","slug":"class-or-interface-s-does-not-exist","errorCode":null,"errorMessage":"Class or interface \"%s\" does not exist","messagePattern":"Class or interface \"(.+?)\" does not exist","errorType":"exception","errorClass":"UnknownClassOrInterfaceException","httpStatus":null,"severity":"error","filePath":"src/Framework/Assert.php","lineNumber":1870,"sourceCode":"    }\n\n    /**\n     * Asserts that a variable is of a given type.\n     *\n     * @template ExpectedType of object\n     *\n     * @param class-string<ExpectedType> $expected\n     *\n     * @throws Exception\n     * @throws ExpectationFailedException\n     * @throws UnknownClassOrInterfaceException\n     *\n     * @phpstan-assert =ExpectedType $actual\n     */\n    final public static function assertInstanceOf(string $expected, mixed $actual, string $message = ''): void\n    {\n        if (!class_exists($expected) && !interface_exists($expected)) {\n            throw new UnknownClassOrInterfaceException($expected);\n        }\n\n        self::assertThat(\n            $actual,\n            new IsInstanceOf($expected),\n            $message,\n        );\n    }\n\n    /**\n     * Asserts that a variable is not of a given type.\n     *\n     * @template ExpectedType of object\n     *\n     * @param class-string<ExpectedType> $expected\n     *\n     * @throws Exception\n     * @throws ExpectationFailedException","sourceCodeStart":1852,"sourceCodeEnd":1888,"githubUrl":"https://github.com/sebastianbergmann/phpunit/blob/f123cdb2a2d49f15025794166cfed8bda8627dd2/src/Framework/Assert.php#L1852-L1888","documentation":"Assert::assertInstanceOf() validates its first argument before evaluating the constraint: if the string is neither an existing nor autoloadable class or interface, it throws PHPUnit\\Framework\\UnknownClassOrInterfaceException ('Class or interface \"%s\" does not exist') instead of running the assertion. This is a test-code error (malformed assertion), not an assertion failure — the $actual value is irrelevant because the check fails first.","triggerScenarios":"self::assertInstanceOf('App\\Servic\\UserRepo', $user) with a typo; a class string built from a variable, config, or data provider that is empty, stale, or differently cased; quoting the ::class constant so it stays a literal ('User::class'); referencing a class from a package missing from the current vendor tree.","commonSituations":"Refactors that rename classes while tests keep old string names; 'composer install --no-dev' CI runs missing dev-only packages; case-sensitive class names on Linux after a rename; leading-backslash inconsistencies in FQCNs built by concatenation.","solutions":["Replace string literals with the ::class constant and a use import: self::assertInstanceOf(UserRepo::class, $user).","Fix the FQCN spelling/namespace and run class_exists('The\\Fqcn') in 'php -r' to confirm the autoloader resolves it.","Run 'composer dump-autoload' (or a full 'composer install') if the class exists on disk but is not autoloaded.","For dynamic class names, validate the string before the assertion with class_exists()/interface_exists() and fail with a clear message."],"exampleFix":"// before\nself::assertInstanceOf('App\\Servic\\UserRepository', $user);\n\n// after\nuse App\\Service\\UserRepository;\n\nself::assertInstanceOf(UserRepository::class, $user);","handlingStrategy":"type-guard","validationCode":"if (!class_exists($expected) && !interface_exists($expected)) {\n    self::fail('Unknown class or interface: ' . $expected . ' (fix the FQCN or autoload mapping)');\n}\n\nself::assertInstanceOf($expected, $actual);","typeGuard":"/** @phpstan-assert class-string $name */\nfunction assertValidTypeString(string $name): void\n{\n    if (!class_exists($name) && !interface_exists($name)) {\n        throw new InvalidArgumentException(\"Class or interface '{$name}' does not exist\");\n    }\n}","tryCatchPattern":null,"preventionTips":["Use ClassName::class (with a use import) instead of quoted FQCN strings in assertions.","Keep dev dependencies installed in CI so referenced contract classes always exist.","Validate data-provider-supplied class strings before passing them to assertions."],"tags":["phpunit","assertion","class-not-found","typo","autoload","php"],"backgroundTag":"class-or-interface-not-found","analyzedSha":"f123cdb2a2d49f15025794166cfed8bda8627dd2","analyzedAt":"2026-08-23T01:20:58.058Z","schemaVersion":2},"datasetVersion":"2026-08-23T08:06:27.607Z"}