{"record":{"id":"dd47cca2be8f88b7","repo":"sebastianbergmann/phpunit","slug":"trying-to-configure-method-s-which-cannot-be-co","errorCode":null,"errorMessage":"Trying to configure method \"%s\" which cannot be configured because it does not exist, has not been specified, is final, or is static","messagePattern":"Trying to configure method \"(.+?)\" which cannot be configured because it does not exist, has not been specified, is final, or is static","errorType":"exception","errorClass":"MethodCannotBeConfiguredException","httpStatus":null,"severity":"error","filePath":"src/Framework/MockObject/Runtime/AbstractInvocationImplementation.php","lineNumber":92,"sourceCode":"    {\n        if ($this->matcher->hasMethodNameRule()) {\n            throw new MethodNameAlreadyConfiguredException;\n        }\n\n        if ($constraint instanceof PropertyHook) {\n            $constraint = $constraint->asString();\n        }\n\n        if (is_string($constraint)) {\n            $this->configurableMethodNames ??= array_flip(\n                array_map(\n                    static fn (ConfigurableMethod $configurable) => strtolower($configurable->name()),\n                    $this->configurableMethods,\n                ),\n            );\n\n            if (!array_key_exists(strtolower($constraint), $this->configurableMethodNames)) {\n                throw new MethodCannotBeConfiguredException($constraint);\n            }\n        }\n\n        $this->matcher->setMethodNameRule(new Rule\\MethodName($constraint));\n\n        return $this;\n    }\n\n    /**\n     * @return $this\n     */\n    final public function will(Stub $stub): InvocationStubber\n    {\n        $this->matcher->setStub($stub);\n\n        return $this;\n    }\n","sourceCodeStart":74,"sourceCodeEnd":110,"githubUrl":"https://github.com/sebastianbergmann/phpunit/blob/f123cdb2a2d49f15025794166cfed8bda8627dd2/src/Framework/MockObject/Runtime/AbstractInvocationImplementation.php#L74-L110","documentation":"Thrown by Invocation implementation when you call ->method($name) on a mock/stub builder and $name (compared lower-case against the double's configurableMethods list) is not configurable. A method is configurable only if it exists on the double and is neither final nor static; for partial mocks (onlyMethods()) it must also have been included in the method list.","triggerScenarios":"Typo in ->method('savve') (matching is case-insensitive, so only wrong characters matter); configuring a method you excluded via onlyMethods(['otherMethod']); ->method() on a final method or a static method; configuring an interface method on a stub of a different interface; ->method('__construct').","commonSituations":"Partial mocks where production code calls a method the test author forgot to list in onlyMethods(); mocking classes with final methods (common after a dependency made methods final); upgrading a dependency whose method became final or static; using createStub() for an intersection of interfaces and configuring a method from a third interface.","solutions":["Check the method exists on the doubled type and is not final/static: (new ReflectionMethod(C::class, 'name'))->isFinal().","For partial mocks, add the method to onlyMethods([...]) (or switch to excludeMethods()/addMethods() as appropriate).","If the method is final, remove the ->method() expectation and let the real implementation run, or ask the upstream library to un-finalize it (or use a wrapper interface you control).","Fix the typo; the comparison is case-insensitive, so capitalization is not the problem."],"exampleFix":"// before\n$mock = $this->getMockBuilder(Service::class)\n    ->onlyMethods(['authorize'])\n    ->getMock();\n$mock->expects($this->once())->method('charge'); // charge() not in list\n\n// after\n$mock = $this->getMockBuilder(Service::class)\n    ->onlyMethods(['authorize', 'charge'])\n    ->getMock();\n$mock->expects($this->once())->method('charge');","handlingStrategy":"validation","validationCode":"$reflection = new ReflectionClass(Service::class);\n$configurable = [];\nforeach ($reflection->getMethods() as $m) {\n    if (!$m->isFinal() && !$m->isStatic() && in_array($m->getName(), $wanted, true)) {\n        $configurable[] = $m->getName();\n    }\n}","typeGuard":"function isConfigurable(string $class, string $method, array $partialList = null): bool\n{\n    $r = new ReflectionClass($class);\n    if (!$r->hasMethod($method)) {\n        return false;\n    }\n    $m = $r->getMethod($method);\n\n    return !$m->isFinal()\n        && !$m->isStatic()\n        && ($partialList === null || in_array($method, $partialList, true));\n}","tryCatchPattern":"try {\n    $mock->expects($this->once())->method($name);\n} catch (PHPUnit\\Framework\\MockObject\\MethodCannotBeConfiguredException $e) {\n    // check reflection for final/static and adjust the onlyMethods() list\n}","preventionTips":["Keep the onlyMethods() list in the same test method as the expectations that use it so they stay in sync.","Before mocking a class for the first time, scan it for final/static methods and design the partial mock around them.","When upgrading dependencies, grep their changelogs for 'final' keyword additions to methods you stub."],"tags":["phpunit","mock-object","partial-mock","final-method","method-not-found"],"backgroundTag":"mock-method-not-configurable","analyzedSha":"f123cdb2a2d49f15025794166cfed8bda8627dd2","analyzedAt":"2026-08-23T01:20:58.058Z","schemaVersion":2},"datasetVersion":"2026-08-23T08:06:27.607Z"}