messenger-test icon indicating copy to clipboard operation
messenger-test copied to clipboard

Cannot generate lazy proxy: class "Zenstruck\Messenger\Test\Bus\TestBus" is final

Open FabienWebavenir opened this issue 1 month ago • 4 comments

When running tests or building the container in the test environment after update to 7.3.4, Symfony fails to generate a lazy proxy for the messenger bus argument and throws:

In ProxyHelper.php line 139: Cannot generate lazy proxy: class "Zenstruck\Messenger\Test\Bus\TestBus" is final.

I attempted to work around the issue by modifying services.yaml, but I was unsuccessful. I use multiple buses in the system.

buses:
   command.bus:
        middleware:
            - doctrine_ping_connection
    query.bus:
        middleware:
            - validation

FabienWebavenir avatar Oct 31 '25 08:10 FabienWebavenir

hi @FabienWebavenir

strange that this is not reproduced by our testsuite 🤔

I just run it with sf 7.3.4 + php 8.3

Details

➜ composer info symfony/*
symfony/browser-kit 7.3.2 Simulates the behavior of a web browser, allowing you to make requests, click on links and submit forms programmatically symfony/cache 7.3.5 Provides extended PSR-6, PSR-16 (and tags) implementations symfony/cache-contracts 3.6.0 Generic abstractions related to caching symfony/clock 7.3.0 Decouples applications from the system clock symfony/config 7.3.4 Helps you find, load, combine, autofill and validate configuration values of any kind symfony/dependency-injection 7.3.4 Allows you to standardize and centralize the way objects are constructed in your application symfony/deprecation-contracts 3.6.0 A generic function and convention to trigger deprecation notices symfony/dom-crawler 7.3.3 Eases DOM navigation for HTML and XML documents symfony/error-handler 7.3.4 Provides tools to manage errors and ease debugging PHP code symfony/event-dispatcher 7.3.3 Provides tools that allow your application components to communicate with each other by dispatching events and listening to them symfony/event-dispatcher-contracts 3.6.0 Generic abstractions related to dispatching event symfony/filesystem 7.3.2 Provides basic utilities for the filesystem symfony/finder 7.3.5 Finds files and directories via an intuitive fluent interface symfony/framework-bundle 7.3.5 Provides a tight integration between Symfony components and the Symfony full-stack framework symfony/http-foundation 7.3.5 Defines an object-oriented layer for the HTTP specification symfony/http-kernel 7.3.5 Provides a structured process for converting a Request into a Response symfony/messenger 7.3.3 Helps applications send and receive messages to/from other applications or via message queues symfony/phpunit-bridge 7.3.4 Provides utilities for PHPUnit, especially user deprecation notices management symfony/polyfill-ctype 1.33.0 Symfony polyfill for ctype functions symfony/polyfill-mbstring 1.33.0 Symfony polyfill for the Mbstring extension symfony/polyfill-php81 1.33.0 Symfony polyfill backporting some PHP 8.1+ features to lower PHP versions symfony/polyfill-php83 1.33.0 Symfony polyfill backporting some PHP 8.3+ features to lower PHP versions symfony/routing 7.3.4 Maps an HTTP request to a set of configuration variables symfony/service-contracts 3.6.0 Generic abstractions related to writing services symfony/var-dumper 7.3.5 Provides mechanisms for walking through any arbitrary PHP variable symfony/var-exporter 7.3.4 Allows exporting any serializable PHP data structure to plain PHP code symfony/yaml 7.3.5 Loads and dumps YAML files

➜ vendor/bin/simple-phpunit
PHPUnit 9.6.29 by Sebastian Bergmann and contributors.

Testing ................................................................. 65 / 74 ( 87%) ......... 74 / 74 (100%)

Time: 00:00.912, Memory: 34.00 MB

OK (74 tests, 402 assertions)

I think the fix is straightforward: replace the final keyword on the TestBus by a @final PHPDoc.

Any chance you create a reproducer? I'd like to know in which case this could occur

nikophil avatar Nov 03 '25 15:11 nikophil

Hi @nikophil

Thank for you response.

While trying to reproduce the issue on a new project, I identified the source of the error. In my project, I have a CommandBus service with the following constructor:

class CommandBus
{
    use HandleTrait;

    public function __construct(
        #[Lazy] #[Target('command.bus')]
        private MessageBusInterface $messageBus,
    ) {
    }

    /**
     * @return mixed The handler returned value
     */
    public function command(CommandInterface $command): mixed
    {
        return $this->handle($command);
    }

    public function getMessageBus(): MessageBusInterface
    {
        return $this->messageBus;
    }
}

Setting it to #[Lazy] causes this error during testing because it injects TestBus, which is final.

FabienWebavenir avatar Nov 03 '25 18:11 FabienWebavenir

cool, thanks for the answer!

Actually in my previous answer, I was about to ask if you were using a #[Lazy] attribute 😅

But this is weird, because you're injecting an interface, it should not create this kind of problem 🤔

which PHP version are you using? Could also find which Symfony version is the culprit and which package? (framework bundle, symfony/di or symfony/var-exporter?)

thanks!

nikophil avatar Nov 03 '25 18:11 nikophil

I’ve created a repository to reproduce the issue. There’s no real logic in it, but it allows testing: https://github.com/FabienWebavenir/zenstruck-messenger-test

When running the tests, I do get the error. The file with the Lazy attribute is App\Core\MessageBus\CommandBus.

make build
make up
make test

FabienWebavenir avatar Nov 04 '25 06:11 FabienWebavenir