{"record":{"id":"e06c7591661e9e54","repo":"sebastianbergmann/phpunit","slug":"class-or-interface-s-does-not-exist-e06c75","errorCode":null,"errorMessage":"Class or interface \"%s\" does not exist","messagePattern":"Class or interface \"(.+?)\" does not exist","errorType":"exception","errorClass":"UnknownTypeException","httpStatus":null,"severity":"error","filePath":"src/Framework/MockObject/Generator/Generator.php","lineNumber":697,"sourceCode":"                '__halt_compiler' => true,\n            ];\n\n            if (version_compare(PHP_VERSION, '8.5', '>=')) {\n                self::$excludedMethodNames['__sleep']  = true;\n                self::$excludedMethodNames['__wakeup'] = true;\n            }\n        }\n\n        return isset(self::$excludedMethodNames[$name]);\n    }\n\n    /**\n     * @throws UnknownTypeException\n     */\n    private function ensureKnownType(string $type): void\n    {\n        if (!class_exists($type) && !interface_exists($type)) {\n            throw new UnknownTypeException($type);\n        }\n    }\n\n    /**\n     * @param ?list<non-empty-string> $methods\n     *\n     * @throws DuplicateMethodException\n     * @throws InvalidMethodNameException\n     */\n    private function ensureValidMethods(?array $methods): void\n    {\n        if ($methods === null) {\n            return;\n        }\n\n        foreach ($methods as $method) {\n            if (preg_match('~\\A[a-zA-Z_\\x7f-\\xff][a-zA-Z0-9_\\x7f-\\xff]*\\z~', (string) $method) === 0) {\n                throw new InvalidMethodNameException((string) $method);","sourceCodeStart":679,"sourceCodeEnd":715,"githubUrl":"https://github.com/sebastianbergmann/phpunit/blob/f123cdb2a2d49f15025794166cfed8bda8627dd2/src/Framework/MockObject/Generator/Generator.php#L679-L715","documentation":"Before building a test double for a type name, PHPUnit's Generator::ensureKnownType() checks that the string denotes an existing class or interface; otherwise it throws UnknownTypeException. This is the first gate inside testDouble() and catches bad type names before reflection or code generation is attempted.","triggerScenarios":"createMock('App\\Servces\\Mailer') (typo), createMock($typeName) with a dynamic name that is null/empty/mangled, createMock(SomeClass::class) where SomeClass is not imported or its package is not autoloaded in the test runtime, or names built by string concatenation with wrong separators (leading backslash is fine, wrong case or missing namespace is not).","commonSituations":"Data-driven tests generating mock types from configuration; refactors renaming classes while the string literal in tests lags behind; composer classmap stale after new files added; running an isolated test file whose dependencies were never autoloaded; CI missing a dev package.","solutions":["Correct the type name; prefer SomeClass::class over string literals so the autoloader resolves it at compile time","Run composer dump-autoload and make sure the file/package defining the type is installed and autoloadable in the test environment"],"exampleFix":"// before\n$mock = $this->createMock('App\\Service\\Mailler'); // typo\n\n// after\nuse App\\Service\\Mailer;\n$mock = $this->createMock(Mailer::class);","handlingStrategy":"validation","validationCode":"if (!class_exists($type) && !interface_exists($type)) {\n    $this->markTestSkipped(\"Cannot double unknown type: $type\");\n}\n$mock = $this->createMock($type);","typeGuard":"function isMockableType(string $type): bool\n{\n    if (!class_exists($type) && !interface_exists($type)) {\n        return false;\n    }\n    $r = new ReflectionClass($type);\n    return !$r->isAnonymous() && !$r->isEnum() && !$r->isFinal();\n}","tryCatchPattern":null,"preventionTips":["Pass Type::class constants, never hand-built strings, to createMock()","Run composer dump-autoload after adding or moving classes; verify CI installs the package owning the type"],"tags":["php","phpunit","mockbuilder","class-not-found","autoloading","createmock"],"backgroundTag":"class-not-found","analyzedSha":"f123cdb2a2d49f15025794166cfed8bda8627dd2","analyzedAt":"2026-08-23T01:20:58.058Z","schemaVersion":2},"datasetVersion":"2026-08-23T08:06:27.607Z"}