1

I try to mock readonly class from PHP 8.2 in PHPUnit and got next error:

Symfony\Component\ErrorHandler\Error\FatalError^ {#7 #message: "Compile Error: Non-readonly class Mock_Provider_f80b7c4d cannot extend readonly class App\Validator\Password\Rule\Provider" #code: 0 #file: "/var/www/html/teach-me/vendor/phpunit/phpunit/src/Framework/MockObject/MockClass.php(51) : eval()'d code" #line: 3 -error: array:4 [ "type" => 64 "message" => "Non-readonly class Mock_Provider_f80b7c4d cannot extend readonly class App\Validator\Password\Rule\Provider" "file" => "/var/www/html/teach-me/vendor/phpunit/phpunit/src/Framework/MockObject/MockClass.php(51) : eval()'d code" "line" => 3 ] }

I think this problem appears because PHPUnit creates default non-readonly class for mocked object. Is there a way to force the creation of a readonly class?

"phpunit/phpunit": "^9.5"

I removed readonly keyword from my class and this error disappeared. I would like to use the new features of PHP, but without the ability to mock objects, this is not possible. Perhaps I am doing something wrong and the problem is not at all what I think?

matiaslauriti
  • 7,065
  • 4
  • 31
  • 43

2 Answers2

1

If you couldn't find a solution, this might help: https://packagist.org/packages/zoltanka/bypass-readonly

That is not the best solution because essentially it changes the code and also makes the tests slower.

But I think it won't be possible soon to mock readonly classes because of how the mocked objects in PHPUnit work. They must hold some information that are changing after creation.

Dharman
  • 30,962
  • 25
  • 85
  • 135
Zoltán Fekete
  • 504
  • 1
  • 6
  • 22
0

It is illegal to extend a readonly class with a normal class, read the PHP RFC. Whatever you are using to mock the class, it will not be able to mock it, as the mock class must be readonly too to be able to extend it (and have all the mocking abilities).

It is very weird to mock a readonly class, so shared your code please, and we may be able to help you...

matiaslauriti
  • 7,065
  • 4
  • 31
  • 43
  • 1
    Sadly, it well seems like just a personal preference by the mantainer. https://github.com/sebastianbergmann/phpunit/pull/5113/files. I find it a really bad practice to enfore how others should work in this extent. Nothing really justifies this decision, nor I found no reasoning. – Zoltán Fekete May 05 '23 at 06:52
  • 1
    I will say it again, it is ILLEGAL (FatalError) to extend a readonly class with a nornal class... It could be solved with Reflection but still, maybe try Mockery, not PHPUnit mocks... – matiaslauriti May 05 '23 at 15:32
  • Apperently I found out why was it working for some time. There was a bug in PHP that has been fixed. Which allowed the readonly classes to have traits **without** readonly properties. And since the Mocked objects have a trait to carry all the mock informations, it worked. I don't expect it to be working for a while. – Zoltán Fekete May 12 '23 at 08:37
  • @ZoltánFekete bug or just a non-desired behavior that got fixed? do you have any links to that so I can also learn about it, pease? – matiaslauriti May 12 '23 at 18:03
  • Actually I also encountered it after my tests were failing: https://github.com/php/php-src/issues/9285 – Zoltán Fekete May 13 '23 at 20:04