Skip to content

Commit b615a67

Browse files
committed
bug #50710 [FrameworkBundle] Fix setting decorated services during tests (nicolas-grekas)
This PR was merged into the 6.3 branch. Discussion ---------- [FrameworkBundle] Fix setting decorated services during tests | Q | A | ------------- | --- | Branch? | 6.3 | Bug fix? | yes | New feature? | no | Deprecations? | no | Tickets | - | License | MIT | Doc PR | - When a service is decorated, setting this service with the test container should set the inner service, not the outer one. Spotted while trying to set a custom scoped http-client in a test case, which was failing because this replaced the traceable+retryable+etc decoration chain we put on top of custom clients. Commits ------- b08f3cd [FrameworkBundle] Fix setting decorated services during tests
2 parents 35675ee + b08f3cd commit b615a67

File tree

10 files changed

+55
-72
lines changed

10 files changed

+55
-72
lines changed

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,9 @@ public function process(ContainerBuilder $container)
4141
if ($id !== $target) {
4242
$renamedIds[$id] = $target;
4343
}
44+
if ($inner = $definitions[$target]->getTag('container.decorator')[0]['inner'] ?? null) {
45+
$renamedIds[$id] = $inner;
46+
}
4447
} else {
4548
unset($privateServices[$id]);
4649
}

src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/TestBundle/TestServiceContainer/PrivateService.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,5 @@
1313

1414
class PrivateService
1515
{
16+
public $inner;
1617
}

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

Lines changed: 0 additions & 61 deletions
This file was deleted.

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

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
use Symfony\Bundle\FrameworkBundle\Tests\Functional\Bundle\TestBundle\TestServiceContainer\PrivateService;
1717
use Symfony\Bundle\FrameworkBundle\Tests\Functional\Bundle\TestBundle\TestServiceContainer\PublicService;
1818
use Symfony\Bundle\FrameworkBundle\Tests\Functional\Bundle\TestBundle\TestServiceContainer\UnusedPrivateService;
19+
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
1920

2021
class TestServiceContainerTest extends AbstractWebTestCase
2122
{
@@ -40,6 +41,33 @@ public function testThatPrivateServicesAreAvailableIfTestConfigIsEnabled()
4041
$this->assertFalse(static::getContainer()->has(UnusedPrivateService::class));
4142
}
4243

44+
public function testThatPrivateServicesCanBeSetIfTestConfigIsEnabled()
45+
{
46+
static::bootKernel(['test_case' => 'TestServiceContainer']);
47+
48+
$container = static::getContainer();
49+
50+
$service = new \stdClass();
51+
52+
$container->set('private_service', $service);
53+
$this->assertSame($service, $container->get('private_service'));
54+
55+
$this->expectException(InvalidArgumentException::class);
56+
$this->expectExceptionMessage('The "private_service" service is already initialized, you cannot replace it.');
57+
$container->set('private_service', new \stdClass());
58+
}
59+
60+
public function testSetDecoratedService()
61+
{
62+
static::bootKernel(['test_case' => 'TestServiceContainer']);
63+
64+
$container = static::getContainer();
65+
66+
$service = new PrivateService();
67+
$container->set('decorated', $service);
68+
$this->assertSame($service, $container->get('decorated')->inner);
69+
}
70+
4371
/**
4472
* @doesNotPerformAssertions
4573
*/

src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/TestServiceContainer/services.yml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,18 @@ services:
88

99
private_service: '@Symfony\Bundle\FrameworkBundle\Tests\Functional\Bundle\TestBundle\TestServiceContainer\PrivateService'
1010

11+
decorated:
12+
class: Symfony\Bundle\FrameworkBundle\Tests\Functional\Bundle\TestBundle\TestServiceContainer\PrivateService
13+
1114
Symfony\Bundle\FrameworkBundle\Tests\Functional\Bundle\TestBundle\TestServiceContainer\PublicService:
1215
public: true
1316
arguments:
1417
- '@Symfony\Bundle\FrameworkBundle\Tests\Functional\Bundle\TestBundle\TestServiceContainer\NonPublicService'
1518
- '@Symfony\Bundle\FrameworkBundle\Tests\Functional\Bundle\TestBundle\TestServiceContainer\PrivateService'
19+
- '@decorated'
20+
21+
decorator:
22+
class: Symfony\Bundle\FrameworkBundle\Tests\Functional\Bundle\TestBundle\TestServiceContainer\PrivateService
23+
decorates: decorated
24+
properties:
25+
inner: '@.inner'

src/Symfony/Bundle/FrameworkBundle/composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
"ext-xml": "*",
2222
"symfony/cache": "^5.4|^6.0",
2323
"symfony/config": "^6.1",
24-
"symfony/dependency-injection": "^6.3",
24+
"symfony/dependency-injection": "^6.3.1",
2525
"symfony/deprecation-contracts": "^2.5|^3",
2626
"symfony/error-handler": "^6.1",
2727
"symfony/event-dispatcher": "^5.4|^6.0",

src/Symfony/Component/DependencyInjection/Compiler/DecoratorServicePass.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ public function process(ContainerBuilder $container)
4242
$definitions->insert([$id, $definition], [$decorated[2], --$order]);
4343
}
4444
$decoratingDefinitions = [];
45+
$decoratedIds = [];
4546

4647
$tagsToKeep = $container->hasParameter('container.behavior_describing_tags')
4748
? $container->getParameter('container.behavior_describing_tags')
@@ -58,6 +59,7 @@ public function process(ContainerBuilder $container)
5859
$renamedId = $id.'.inner';
5960
}
6061

62+
$decoratedIds[$inner] ??= $renamedId;
6163
$this->currentId = $renamedId;
6264
$this->processValue($definition);
6365

@@ -114,7 +116,7 @@ public function process(ContainerBuilder $container)
114116
}
115117

116118
foreach ($decoratingDefinitions as $inner => $definition) {
117-
$definition->addTag('container.decorator', ['id' => $inner]);
119+
$definition->addTag('container.decorator', ['id' => $inner, 'inner' => $decoratedIds[$inner]]);
118120
}
119121
}
120122

src/Symfony/Component/DependencyInjection/Tests/Compiler/DecoratorServicePassTest.php

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,7 @@ public function testProcessWithInvalidDecorated()
161161
public function testProcessNoInnerAliasWithInvalidDecorated()
162162
{
163163
$container = new ContainerBuilder();
164-
$decoratorDefinition = $container
164+
$container
165165
->register('decorator')
166166
->setDecoratedService('unknown_decorated', null, 0, ContainerInterface::NULL_ON_INVALID_REFERENCE)
167167
;
@@ -173,7 +173,7 @@ public function testProcessNoInnerAliasWithInvalidDecorated()
173173
public function testProcessWithInvalidDecoratedAndWrongBehavior()
174174
{
175175
$container = new ContainerBuilder();
176-
$decoratorDefinition = $container
176+
$container
177177
->register('decorator')
178178
->setDecoratedService('unknown_decorated', null, 0, 12)
179179
;
@@ -198,7 +198,7 @@ public function testProcessMovesTagsFromDecoratedDefinitionToDecoratingDefinitio
198198
$this->process($container);
199199

200200
$this->assertEmpty($container->getDefinition('baz.inner')->getTags());
201-
$this->assertEquals(['bar' => ['attr' => 'baz'], 'foobar' => ['attr' => 'bar'], 'container.decorator' => [['id' => 'foo']]], $container->getDefinition('baz')->getTags());
201+
$this->assertEquals(['bar' => ['attr' => 'baz'], 'foobar' => ['attr' => 'bar'], 'container.decorator' => [['id' => 'foo', 'inner' => 'baz.inner']]], $container->getDefinition('baz')->getTags());
202202
}
203203

204204
public function testProcessMovesTagsFromDecoratedDefinitionToDecoratingDefinitionMultipleTimes()
@@ -221,7 +221,7 @@ public function testProcessMovesTagsFromDecoratedDefinitionToDecoratingDefinitio
221221
$this->process($container);
222222

223223
$this->assertEmpty($container->getDefinition('deco1')->getTags());
224-
$this->assertEquals(['bar' => ['attr' => 'baz'], 'container.decorator' => [['id' => 'foo']]], $container->getDefinition('deco2')->getTags());
224+
$this->assertEquals(['bar' => ['attr' => 'baz'], 'container.decorator' => [['id' => 'foo', 'inner' => 'deco1.inner']]], $container->getDefinition('deco2')->getTags());
225225
}
226226

227227
public function testProcessLeavesServiceLocatorTagOnOriginalDefinition()
@@ -240,7 +240,7 @@ public function testProcessLeavesServiceLocatorTagOnOriginalDefinition()
240240
$this->process($container);
241241

242242
$this->assertEquals(['container.service_locator' => [0 => []]], $container->getDefinition('baz.inner')->getTags());
243-
$this->assertEquals(['bar' => ['attr' => 'baz'], 'foobar' => ['attr' => 'bar'], 'container.decorator' => [['id' => 'foo']]], $container->getDefinition('baz')->getTags());
243+
$this->assertEquals(['bar' => ['attr' => 'baz'], 'foobar' => ['attr' => 'bar'], 'container.decorator' => [['id' => 'foo', 'inner' => 'baz.inner']]], $container->getDefinition('baz')->getTags());
244244
}
245245

246246
public function testProcessLeavesServiceSubscriberTagOnOriginalDefinition()
@@ -259,7 +259,7 @@ public function testProcessLeavesServiceSubscriberTagOnOriginalDefinition()
259259
$this->process($container);
260260

261261
$this->assertEquals(['container.service_subscriber' => [], 'container.service_subscriber.locator' => []], $container->getDefinition('baz.inner')->getTags());
262-
$this->assertEquals(['bar' => ['attr' => 'baz'], 'foobar' => ['attr' => 'bar'], 'container.decorator' => [['id' => 'foo']]], $container->getDefinition('baz')->getTags());
262+
$this->assertEquals(['bar' => ['attr' => 'baz'], 'foobar' => ['attr' => 'bar'], 'container.decorator' => [['id' => 'foo', 'inner' => 'baz.inner']]], $container->getDefinition('baz')->getTags());
263263
}
264264

265265
public function testProcessLeavesProxyTagOnOriginalDefinition()
@@ -278,7 +278,7 @@ public function testProcessLeavesProxyTagOnOriginalDefinition()
278278
$this->process($container);
279279

280280
$this->assertEquals(['proxy' => 'foo'], $container->getDefinition('baz.inner')->getTags());
281-
$this->assertEquals(['bar' => ['attr' => 'baz'], 'foobar' => ['attr' => 'bar'], 'container.decorator' => [['id' => 'foo']]], $container->getDefinition('baz')->getTags());
281+
$this->assertEquals(['bar' => ['attr' => 'baz'], 'foobar' => ['attr' => 'bar'], 'container.decorator' => [['id' => 'foo', 'inner' => 'baz.inner']]], $container->getDefinition('baz')->getTags());
282282
}
283283

284284
public function testCannotDecorateSyntheticService()

src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/anonymous.expected.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,5 +16,5 @@ services:
1616
class: Symfony\Component\DependencyInjection\Tests\Fixtures\StdClassDecorator
1717
public: true
1818
tags:
19-
- container.decorator: { id: decorated }
19+
- container.decorator: { id: decorated, inner: decorator42 }
2020
arguments: [!service { class: stdClass }]

src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/child.expected.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ services:
88
class: Class2
99
public: true
1010
tags:
11-
- container.decorator: { id: bar }
11+
- container.decorator: { id: bar, inner: b }
1212
file: file.php
1313
lazy: true
1414
arguments: [!service { class: Class1 }]

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy