4

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?

1 Answer 1

3

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.

1
  • Apart from whether somehow technically feasible or not, there probably is/was a reason the (base) class has been implemented readonly and therefore questionable if mocks are actually desired. That's not a judgement, just a note on considerations. E.g. I'd check if mocking can be prevented for testing, and if not, provide a mock/spy object for tests within the test suite for starters (not relying on dynamic mocks), YMMV.
    – hakre
    Commented Jul 6 at 22:36

Not the answer you're looking for? Browse other questions tagged or ask your own question.