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
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
- [FrameworkBundle] Fix test-container on kernel reboot, revert to returning the real container from Client::getContainer() — committed to symfony/symfony by nicolas-grekas 6 years ago
- Add services test definitions Create services_test.yaml to make services public when needed for testing. Fixes symfony/symfony#27741 — committed to sonro/cartator by sonro 5 years ago
- Add services test definitions Create services_test.yaml to make services public when needed for testing. See symfony/symfony#27741 — committed to sonro/cartator by sonro 5 years ago
+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&handlersfirst 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 newCommandClassas type hint just to be able to test it? Also consider this scenario: we createServiceX, unittest for it and we are using this service inControllerX. After some time we decide to remove usage ofServiceXinControllerX. 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 inservices.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\ServiceXthat works well in unitTest, copied it asMyServiceX2and 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:containerThere IS alias and we run tests in
ENV=testand 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 in4.1.0and stopped in4.1.1Yep… 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::$containerinstead of$client->getContainer()now. I’m going to update the blog post.