I am migrating our project to Symfony 4. In my test suites, we used PHPUnit for functional tests (I mean, we call endpoints and we check result). Often, we mock services to check different steps.
Since I migrated to Symfony 4, I am facing this issue: SymfonyComponentDependencyInjectionExceptionInvalidArgumentException: The "my.service" service is already initialized, you cannot replace it.
when we redefine it like this : static::$container->set("my.service", $mock);
Only for tests, how can I fix this issue?
Thank you
Advertisement
Answer
Finally, I found a solution. Maybe not the best, but, it’s working:
I created another test container class and I override the services
property using Reflection:
<?php namespace MyBundleTest; use SymfonyBundleFrameworkBundleTestTestContainer as BaseTestContainer; class TestContainer extends BaseTestContainer { private $publicContainer; public function set($id, $service) { $r = new ReflectionObject($this->publicContainer); $p = $r->getProperty('services'); $p->setAccessible(true); $services = $p->getValue($this->publicContainer); $services[$id] = $service; $p->setValue($this->publicContainer, $services); } public function setPublicContainer($container) { $this->publicContainer = $container; }
Kernel.php :
<?php namespace App; use SymfonyComponentHttpKernelKernel as BaseKernel; class Kernel extends BaseKernel { use MicroKernelTrait; public function getOriginalContainer() { if(!$this->container) { parent::boot(); } /** @var Container $container */ return $this->container; } public function getContainer() { if ($this->environment == 'prod') { return parent::getContainer(); } /** @var Container $container */ $container = $this->getOriginalContainer(); $testContainer = $container->get('my.test.service_container'); $testContainer->setPublicContainer($container); return $testContainer; }
It’s really ugly, but it’s working.