php test_error ai_generated true

PHPUnit\Framework\MockObject\RuntimeException: Trying to configure a method "getUser" that does not exist on mock class "App\Service\UserService"

ID: php/phpunit-mock-builder-method-exists

Also available as: JSON · Markdown · 中文
90%Fix Rate
88%Confidence
1Evidence
2023-11-20First Seen

Version Compatibility

VersionStatusIntroducedDeprecatedNotes
PHPUnit 10.5 active
PHPUnit 11.0 active

Root Cause

PHPUnit's mock builder is trying to configure a method that does not exist on the mocked class, usually due to a typo in the method name or the method being private/final/static.

generic

中文

PHPUnit 的模拟构建器试图配置模拟类上不存在的方法,通常是由于方法名拼写错误或该方法为私有/最终/静态方法。

Official Documentation

https://docs.phpunit.de/en/10.5/test-doubles.html#test-double-apis

Workarounds

  1. 95% success Verify the method name spelling and visibility. Run `php -r "echo (new ReflectionMethod('App\\Service\\UserService', 'getUser'))->isPublic() ? 'public' : 'not public';"` to check if the method exists and is public.
    Verify the method name spelling and visibility. Run `php -r "echo (new ReflectionMethod('App\\Service\\UserService', 'getUser'))->isPublic() ? 'public' : 'not public';"` to check if the method exists and is public.
  2. 80% success If the method is static or final, use `onlyMethods()` with the method name, or refactor the class to make the method non-final. Example: `$mock = $this->getMockBuilder(UserService::class)->onlyMethods(['getUser'])->getMock();`
    If the method is static or final, use `onlyMethods()` with the method name, or refactor the class to make the method non-final. Example: `$mock = $this->getMockBuilder(UserService::class)->onlyMethods(['getUser'])->getMock();`

中文步骤

  1. Verify the method name spelling and visibility. Run `php -r "echo (new ReflectionMethod('App\\Service\\UserService', 'getUser'))->isPublic() ? 'public' : 'not public';"` to check if the method exists and is public.
  2. If the method is static or final, use `onlyMethods()` with the method name, or refactor the class to make the method non-final. Example: `$mock = $this->getMockBuilder(UserService::class)->onlyMethods(['getUser'])->getMock();`

Dead Ends

Common approaches that don't work:

  1. Adding a @runInSeparateProcess annotation to the test method to isolate state 90% fail

    This does not fix the method name mismatch; it just runs the test in a separate process, which may mask the error but the underlying issue persists.

  2. Using createMock() instead of getMockBuilder() assuming it's a builder issue 85% fail

    createMock() also uses the same method existence check internally; the error will still occur if the method does not exist.