Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Invalid "phpunit.mockMethod" error #227

Closed
liayn opened this issue Mar 26, 2025 · 8 comments
Closed

Invalid "phpunit.mockMethod" error #227

liayn opened this issue Mar 26, 2025 · 8 comments

Comments

@liayn
Copy link

liayn commented Mar 26, 2025

We are getting:

Trying to mock an undefined method addCacheTags() on class TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController

PHP: 8.4
phpunit: 10.5.45
phpstan: 2.1.11
phpstan-phpunit: 2.0.5

It looks like #222 is related to this.

@liayn
Copy link
Author

liayn commented Mar 26, 2025

Downgrading to phpstan-phpunit: 2.0.4 solves the issue.

@ondrejmirtes
Copy link
Member

Please show code that causes this error. A full example that we can reproduce the problem with.

@liayn
Copy link
Author

liayn commented Mar 26, 2025

I tried to extract this from our code base:

use TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController;

class SomeTest extends BaseTestCase {

protected MockObject|TypoScriptFrontendController $tsfe;

protected function setUp(): void
{
    $this->tsfe = $this->getMockBuilder(TypoScriptFrontendController::class)
            ->onlyMethods(['addCacheTags', 'getLanguage'])
            ->disableOriginalConstructor()
            ->getMock();

   $language = ....;
// this works
   $this->tsfe->method('getLanguage')->willReturn($language);
}

#[Test]
public function sometest(): void
{
// this causes the error
     $this->tsfe->expects(self::once())->method('addCacheTags');
}

This is the mocked class:
https://github.com/TYPO3/typo3/blob/12.4/typo3/sysext/frontend/Classes/Controller/TypoScriptFrontendController.php

@ondrejmirtes
Copy link
Member

This:

protected MockObject|TypoScriptFrontendController $tsfe;

Should be an intersection type:

protected MockObject&TypoScriptFrontendController $tsfe;

Can you try that?

@ondrejmirtes
Copy link
Member

I confirm that using the proper intersection type fixes it.

@liayn
Copy link
Author

liayn commented Mar 26, 2025

Yes, fixes it.

So we have two issues here now:

  • The error message is misleading, as it claims something that is not true. ("method X does not exist on Y", but it does)
  • Older code-bases where intersection types haven't been used yet are now getting errors despite 2.0.5 being a bugfix-release (in SemVer terms)

I have no problem with adjusting the code-base to intersection types, but those who need to support PHP < 8.1 will.

@ondrejmirtes
Copy link
Member

Your code has always been wrong because it's been reporting this error even on 2.0.4 and prior:

  40     Call to an undefined method aaa\Foo|PHPUnit\Framework\MockObject\MockObject::expects().
         🪪  method.notFound

That said, I managed to improve the extension not to report "method X does not exist on Y": 0aef32f

I have no problem with adjusting the code-base to intersection types, but those who need to support PHP < 8.1 will.

Intersection types work in PHPDocs too. In fact, it was where they originated: https://phpstan.org/blog/union-types-vs-intersection-types

@liayn
Copy link
Author

liayn commented Mar 26, 2025

Your code has always been wrong because

Argss... I forgot to disable the old baseline for the test. Sorry.

That said, I managed to improve the extension not to report "method X does not exist on Y": 0aef32f

🤝👍

Thanks for the very fast support here. Highly appreciated.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants