phpunit icon indicating copy to clipboard operation
phpunit copied to clipboard

Manually instantiated test doubles are broken since PHPUnit 11.2

Open ostrolucky opened this issue 3 months ago • 3 comments

Q A
PHPUnit version 11.2.0 ... dev-main e0aea4c
PHP version 8.4.6
Installation Method Composer

Summary

Up to PHPUnit 11.1.* you can easily instantiate mock yourself. Calling methods on such objects was working fine. Since PHPUnit 11.2.0 (still broken in latest phpunit 12.x) this is no longer the case. You can still instantiate such class, but calling methods on it is broken.

Our use case was feed the FQCN of a mock class to Symfony DI container. DI container is then in charge of instantiating objects.

Ref https://github.com/doctrine/DoctrineBundle/pull/2040

Issue6362Test.php

<?php declare(strict_types=1);
namespace PHPUnit\TestFixture\Issue6362;

use PHPUnit\Framework\TestCase;

interface I
{
    public function m(): string;
}

final class Issue6362Test extends TestCase
{
    public function testOne(): void
    {
        $class = $this->createStub(I::class)::class;

        $o = new $class;

        $o->m();
    }
}

Actual

PHPUnit Started (PHPUnit 12.4-g59f70b3a79 using PHP 8.4.12 (cli) on Linux)
Test Runner Configured
Event Facade Sealed
Test Suite Loaded (1 test)
Test Runner Started
Test Suite Sorted
Test Runner Execution Started (1 test)
Test Suite Started (PHPUnit\TestFixture\Issue6362\Issue6362Test, 1 test)
Test Preparation Started (PHPUnit\TestFixture\Issue6362\Issue6362Test::testOne)
Test Prepared (PHPUnit\TestFixture\Issue6362\Issue6362Test::testOne)
Test Stub Created (PHPUnit\TestFixture\Issue6362\I)
Test Errored (PHPUnit\TestFixture\Issue6362\Issue6362Test::testOne)
Typed property TestStub_I_7653f44f::$__phpunit_state must not be accessed before initialization
Test Finished (PHPUnit\TestFixture\Issue6362\Issue6362Test::testOne)
Test Suite Finished (PHPUnit\TestFixture\Issue6362\Issue6362Test, 1 test)
Test Runner Execution Finished
Test Runner Finished
PHPUnit Finished (Shell Exit Code: 2)

Expected

PHPUnit Started (PHPUnit 12.4-g59f70b3a79 using PHP 8.4.12 (cli) on Linux)
Test Runner Configured
Event Facade Sealed
Test Suite Loaded (1 test)
Test Runner Started
Test Suite Sorted
Test Runner Execution Started (1 test)
Test Suite Started (PHPUnit\TestFixture\Issue6362\Issue6362Test, 1 test)
Test Preparation Started (PHPUnit\TestFixture\Issue6362\Issue6362Test::testOne)
Test Prepared (PHPUnit\TestFixture\Issue6362\Issue6362Test::testOne)
Test Stub Created (PHPUnit\TestFixture\Issue6362\I)
Test Passed (PHPUnit\TestFixture\Issue6362\Issue6362Test::testOne)
Test Considered Risky (PHPUnit\TestFixture\Issue6362\Issue6362Test::testOne)
This test did not perform any assertions
Test Finished (PHPUnit\TestFixture\Issue6362\Issue6362Test::testOne)
Test Suite Finished (PHPUnit\TestFixture\Issue6362\Issue6362Test, 1 test)
Test Runner Execution Finished
Test Runner Finished
PHPUnit Finished (Shell Exit Code: 0)

ostrolucky avatar Sep 12 '25 09:09 ostrolucky

you can easily instantiate mock yourself

This was never a supported use case, sorry.

sebastianbergmann avatar Sep 12 '25 09:09 sebastianbergmann

That's kinda semantics discussion. It was a use case that was working up to Phpunit 11.2, regardless if it was documented or declared as intended to be supported. I mean, these changes broke this https://github.com/sebastianbergmann/phpunit/pull/5804, surely that wasn't your intention? You just didn't know this could be the side effect. Would you entertain idea of someone fixing it, or are you going to actively block such attempt?

ostrolucky avatar Sep 12 '25 09:09 ostrolucky

I mean, these changes broke this https://github.com/sebastianbergmann/phpunit/pull/5804, surely that wasn't your intention?

This sentence does not make sense to me: "These changes" and "this https://github.com/sebastianbergmann/phpunit/pull/5804" mean the same thing. These are are the changes that were made in PHPUnit 11.2 to support doubling of readonly classes.

It was a use case that was working up to Phpunit 11.2

A use case that relied on internal implementation details that are not covered by the backward compatibility promise for PHPUnit.

Would you entertain idea of someone fixing it, or are you going to actively block such attempt?

I am not going to actively block such an attempt.

However, all I can promise is that I will review a pull request that restores your use case. I am concerned, though, that the necessary changes will introduce more complexity than I am comfortable with.

You will also need to convince me that your use case is valid and must be supported. Personally, I don't see the point of using a dependency injection container with test doubles as you describe.

sebastianbergmann avatar Sep 12 '25 09:09 sebastianbergmann