8000 [FrameworkBundle] Allow setting private services with the test container · symfony/symfony@8f771fc · GitHub
[go: up one dir, main page]

Skip to content

Commit 8f771fc

Browse files
[FrameworkBundle] Allow setting private services with the test container
1 parent 21191d5 commit 8f771fc

File tree

5 files changed

+41
-17
lines changed

5 files changed

+41
-17
lines changed

src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ CHANGELOG
1111
* Add support to pass namespace wildcard in `framework.messenger.routing`
1212
* Deprecate `framework:exceptions` tag, unwrap it and replace `framework:exception` tags' `name` attribute by `class`
1313
* Deprecate the `notifier.logger_notification_listener` service, use the `notifier.notification_logger_listener` service instead
14+
* Allow setting private services with the test container
1415

1516
6.2
1617
---

src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/TestServiceContainerRealRefPass.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,15 +29,23 @@ public function process(ContainerBuilder $container)
2929
$privateContainer = $container->getDefinition('test.private_services_locator');
3030
$definitions = $container->getDefinitions();
3131
$privateServices = $privateContainer->getArgument(0);
32+
$renamedIds = [];
3233

3334
foreach ($privateServices as $id => $argument) {
3435
if (isset($definitions[$target = (string) $argument->getValues()[0]])) {
3536
$argument->setValues([new Reference($target)]);
37+
if ($id !== $target) {
38+
$renamedIds[$id] = $target;
39+
}
3640
} else {
3741
unset($privateServices[$id]);
3842
}
3943
}
4044

4145
$privateContainer->replaceArgument(0, $privateServices);
46+
47+
if ($container->hasDefinition('test.service_container') && $renamedIds) {
48+
$container->getDefinition('test.service_container')->setArgument(2, $renamedIds);
49+
}
4250
}
4351
}

src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/TestServiceContainerWeakRefPass.php

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,9 @@ public function process(ContainerBuilder $container)
3030

3131
$privateServices = [];
3232
$definitions = $container->getDefinitions();
33-
$hasErrors = method_exists(Definition::class, 'hasErrors') ? 'hasErrors' : 'getErrors';
3433

3534
foreach ($definitions as $id => $definition) {
36-
if ($id && '.' !== $id[0] && (!$definition->isPublic() || $definition->isPrivate() || $definition->hasTag('container.private')) && !$definition->$hasErrors() && !$definition->isAbstract()) {
35+
if ($id && '.' !== $id[0] && (!$definition->isPublic() || $definition->isPrivate() || $definition->hasTag('container.private')) && !$definition->hasErrors() && !$definition->isAbstract()) {
3736
$privateServices[$id] = new Reference($id, ContainerBuilder::IGNORE_ON_UNINITIALIZED_REFERENCE);
3837
}
3938
}
@@ -45,7 +44,7 @@ public function process(ContainerBuilder $container)
4544
while (isset($aliases[$target = (string) $alias])) {
4645
$alias = $aliases[$target];
4746
}
48-
if (isset($definitions[$target]) && !$definitions[$target]->$hasErrors() && !$definitions[$target]->isAbstract()) {
47+
if (isset($definitions[$target]) && !$definitions[$target]->hasErrors() && !$definitions[$target]->isAbstract()) {
4948
$privateServices[$id] = new Reference($target, ContainerBuilder::IGNORE_ON_UNINITIALIZED_REFERENCE);
5049
}
5150
}

src/Symfony/Bundle/FrameworkBundle/Test/TestContainer.php

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,13 @@
1313

1414
use Psr\Container\ContainerInterface;
1515
use Symfony\Component\DependencyInjection\Container;
16+
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
1617
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
1718
use Symfony\Component\HttpKernel\KernelInterface;
1819

1920
/**
2021
* A special container used in tests. This gives access to both public and
21-
* private services. The container will not include private services that has
22+
* private services. The container will not include private services that have
2223
* been inlined or removed. Private services will be removed when they are not
2324
* used by other services.
2425
*
@@ -28,13 +29,11 @@
2829
*/
2930
class TestContainer extends Container
3031
{
31-
private KernelInterface $kernel;
32-
private string $privateServicesLocatorId;
33-
34-
public function __construct(KernelInterface $kernel, string $privateServicesLocatorId)
35-
{
36-
$this->kernel = $kernel;
37-
$this->privateServicesLocatorId = $privateServicesLocatorId;
32+
public function __construct(
33+
private KernelInterface $kernel,
34+
private string $privateServicesLocatorId,
35+
private array $renamedIds = [],
36+
) {
3837
}
3938

4039
public function compile()
@@ -69,7 +68,16 @@ public function setParameter(string $name, mixed $value)
6968

7069
public function set(string $id, mixed $service)
7170
{
72-
$this->getPublicContainer()->set($id, $service);
71+
$renamedId = $this->renamedIds[$id] ?? $id;
72+
73+
try {
74+
$this->getPublicContainer()->set($renamedId, $service);
75+
} catch (InvalidArgumentException $e) {
76+
if (!str_starts_with($e->getMessage(), "The \"$renamedId\" service is private")) {
77+
throw $e;
78+
}
79+
$this->getPublicContainer()->privates[$renamedId] = $service;
80+
}
7381
}
7482

7583
public function has(string $id): bool
@@ -104,11 +112,7 @@ public function getRemovedIds(): array
104112

105113
private function getPublicContainer(): Container
106114
{
107-
if (null === $container = $this->kernel->getContainer()) {
108-
throw new \LogicException('Cannot access the container on a non-booted kernel. Did you forget to boot it?');
109-
}
110-
111-
return $container;
115+
return $this->kernel->getContainer() ?? throw new \LogicException('Cannot access the container on a non-booted kernel. Did you forget to boot it?');
112116
}
113117

114118
private function getPrivateContainer(): ContainerInterface

src/Symfony/Bundle/FrameworkBundle/Tests/Functional/KernelTestCaseTest.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,4 +41,16 @@ public function testThatPrivateServicesAreAvailableIfTestConfigIsEnabled()
4141
$this->assertTrue($container->has('private_service'));
4242
$this->assertFalse($container->has(UnusedPrivateService::class));
4343
}
44+
45+
public function testThatPrivateServicesCanBeSetIfTestConfigIsEnabled()
46+
{
47+
static::bootKernel(['test_case' => 'TestServiceContainer']);
48+
49+
$container = static::getContainer();
50+
51+
$service = new \stdClass();
52+
53+
$container->set('private_service', $service);
54+
$this->assertSame($service, $container->get('private_service'));
55+
}
4456
}

0 commit comments

Comments
 (0)
0