symfony: 4.1.1 'Simple service testing' on private services not working after DI changes

Symfony version(s) affected: 4.1.1

Description
This commit made for last SF version 4.1.1 breaks feature brought to in version 4.1.0. Simple service testing doesn’t work anymore. https://symfony.com/blog/new-in-symfony-4-1-simpler-service-testing

https://github.com/symfony/symfony/commit/6764d4e01272b922f6f3c9ab2e3dee2fd19acd43#diff-ce4ed09b11d8fa531159e96df52124f3

How to reproduce

        // class TestX extends \Symfony\Bundle\FrameworkBundle\Test\WebTestCase\WebTestCase
        $client = self::createClient();
        $container = $client->getContainer();
        // Or any private service
        $em = $container->get(EntityManagerInterface::class);

About this issue

  • Original URL
  • State: closed
  • Created 6 years ago
  • Reactions: 2
  • Comments: 16 (7 by maintainers)

Commits related to this issue

Most upvoted comments

+1 I also think this is wrong behaviour, because it breaks Test-driven-development. Building service classes, then testing them, and then start using them inside other services or controllers is a good pattern, but does not work this way. And because it’s not in the docs, users scratch their heads why this (good!) feature seems to be not working.

Great… So in our workflow, where we create commands & handlers first and not using them anywhere we can’t create test for them, because everything will fail? We have to create dummy object where we will set new CommandClass as type hint just to be able to test it? Also consider this scenario: we create ServiceX, unittest for it and we are using this service in ControllerX. After some time we decide to remove usage of ServiceX in ControllerX. Now when we will run all our unittests we will get errors each time. Not because something is wrong with our service, but because it is not used in application anywhere. Whats more error will say that service is not defined/aliased when it is not true, as I defined alias in services.yaml. This service IS defined, so phpUnit should be able to use it - now it is not, because service is not used anywhere.

unittest should not depend on what is used in application but on what is defined and allowed to use.

Oh, yes, that’s expected behavior: the dump:container shows what’s possible to use, while the test container gives access to what’s effectively used only (because we must clean up unused services to have things work). Closing therefor, thanks for submitting.

OK. I found why.

I was scratching my head why some of my services are loaded in test with no problem and other throws error. So I took 1 service My\ServiceX that works well in unitTest, copied it as MyServiceX2 and tried to load it in unitTest - error hit me (cache & dump-autoload done previously).

I opened first controller I found and used this service myControllerAction(MyServiceX2 $x2) and guess what? My unitTest started to work.

If service is not used/autowired anywhere it will not be visible in phpUnit, even if it is visible by console dump:container

bin/console debug:container 'Core\Interfaces\Api\UserApiInterface'

 // This service is an alias for the service LTTSIntegration\Api\UserApi

There IS alias and we run tests in ENV=test and unittest fails to load above service as long as it is not typeHinted somewhere in the app. This is the reason why I still commenting on this topic. I still think this is not proper behavior. Especially if all of this worked in 4.1.0 and stopped in 4.1.1

Yep… make alas for everything and make everything public. I get it… so we are going back to Symfony 3.3?

Thank for the report. We broke this in #27501 because we had no choice and the affected code would be young enough that people (you…) could still do something about it. Sorry about that. The way to go is to use self::$container instead of $client->getContainer() now. I’m going to update the blog post.