{"record":{"id":"122b093a79c6b57a","repo":"sebastianbergmann/phpunit","slug":"static-method-method-name-cannot-be-invoked-on","errorCode":null,"errorMessage":"Static method \"{method_name}\" cannot be invoked on mock object","messagePattern":"Static method \"(.+?)\" cannot be invoked on mock object","errorType":"exception","errorClass":"PHPUnit\\Framework\\MockObject\\BadMethodCallException","httpStatus":null,"severity":"error","filePath":"src/Framework/MockObject/Generator/templates/doubled_static_method.tpl","lineNumber":4,"sourceCode":"\n    {modifier} function {reference}{method_name}({arguments_decl}){return_declaration}\n    {\n        throw new \\PHPUnit\\Framework\\MockObject\\BadMethodCallException('Static method \"{method_name}\" cannot be invoked on mock object');\n    }\n","sourceCodeStart":1,"sourceCodeEnd":6,"githubUrl":"https://github.com/sebastianbergmann/phpunit/blob/f123cdb2a2d49f15025794166cfed8bda8627dd2/src/Framework/MockObject/Generator/templates/doubled_static_method.tpl#L1-L6","documentation":"PHPUnit 10+ doubles static methods in generated mocks/stubs: the template replaces every static method body with a throw of MockObject\\BadMethodCallException('Static method \"X\" cannot be invoked on mock object'). PHPUnit cannot intercept static calls, so calling a static method through the mock's class (or via static:: inside mocked instance code) always fails at runtime with this message.","triggerScenarios":"Creating $mock = $this->createMock(Foo::class) and then invoking $mock::staticMethod() (or static::staticMethod() / self::staticMethod() inside code under test that runs against the mock class). Any static invocation on the doubled class hits the throwing template body.","commonSituations":"Upgrading PHPUnit 9 to 10/11/12 where tests previously worked because static methods kept their real implementation; code under test calling static::create() or static::register() factory hooks that now execute against the mock subclass; helpers like Entity::table() invoked on mock entities.","solutions":["Call the static method on the real class instead of the mock: Foo::staticMethod(), not $mock::staticMethod()","Refactor the code under test so the dependency is an instance method you can mock normally (inject the collaborator)","If the static must run, do not double that class — use the real object, or a hand-written test subclass that overrides the static method","Assert the exception itself when testing that statics are not callable: expectException(BadMethodCallException::class)"],"exampleFix":"// before\n$logger = $this->createMock(FileLogger::class);\nFileLogger::setRetentionPolicy(30); // ok (real class)\n$logger::rotate();                   // BadMethodCallException on PHPUnit 10+\n\n// after\n$logger = $this->createMock(FileLogger::class);\nFileLogger::rotate();                // call statics on the real class\n// better: refactor rotate() into an instance method and configure the mock","handlingStrategy":"type-guard","validationCode":"$method = new ReflectionMethod($mock, $name);\nif ($method->isStatic()) {\n    // call it on the real class, not the double\n    $realClass = $mock::class;\n    // strip the generated Mock_ prefix by calling the original class instead:\n    return $originalClass::$name(...$args);\n}","typeGuard":"static function callsStaticOn(string $class, string $method): bool\n{\n    return (new ReflectionMethod($class, $method))->isStatic();\n}","tryCatchPattern":"use PHPUnit\\Framework\\MockObject\\BadMethodCallException;\n\ntry {\n    $mock->{$name}(...$args);\n} catch (BadMethodCallException $e) {\n    if (str_contains($e->getMessage(), 'cannot be invoked on mock object')) {\n        // static on a double: reroute to the real class or refactor the design\n    }\n    throw $e;\n}","preventionTips":["Treat 'never mock statics' as a review rule: static factories and registries belong on real classes in tests","Prefer constructor/method injection of collaborators so mocks never need static behavior","When upgrading PHPUnit 9 to 10+, grep tests for `::` calls on mock variables and static:: usages in tested code","Hand-write a test subclass overriding statics if a static seam is unavoidable"],"tags":["phpunit","mockobject","static-methods","phpunit-10"],"backgroundTag":"mock-static-method-call","analyzedSha":"f123cdb2a2d49f15025794166cfed8bda8627dd2","analyzedAt":"2026-08-23T01:20:58.058Z","schemaVersion":2},"datasetVersion":"2026-08-23T08:06:27.607Z"}