Adding an integration test for the hirarchy of defaults, instanceof, child, parent definitions

This commit is contained in:
Ryan Weaver 2017-04-11 09:35:46 -04:00 committed by Nicolas Grekas
parent ab86457b12
commit 6d6116b920
4 changed files with 129 additions and 1 deletions

View File

@ -30,6 +30,7 @@ class ResolveInstanceofConditionalsPass implements CompilerPassInterface
$didProcess = false;
foreach ($container->getDefinitions() as $id => $definition) {
if ($definition instanceof ChildDefinition) {
// don't apply "instanceof" to children: it will be applied to their parent
continue;
}
if ($definition !== $processedDefinition = $this->processDefinition($container, $id, $definition)) {

View File

@ -12,6 +12,7 @@
namespace Symfony\Component\DependencyInjection\Compiler;
use Symfony\Component\DependencyInjection\ChildDefinition;
use Symfony\Component\DependencyInjection\Exception\RuntimeException;
/**
* Applies tags inheritance to definitions.
@ -31,7 +32,7 @@ class ResolveTagsInheritancePass extends AbstractRecursivePass
$value->setInheritTags(false);
if (!$this->container->has($parent = $value->getParent())) {
return parent::processValue($value, $isRoot);
throw new RuntimeException(sprintf('Parent definition "%s" does not exist.', $parent));
}
$parentDef = $this->container->findDefinition($parent);

View File

@ -12,7 +12,9 @@
namespace Symfony\Component\DependencyInjection\Tests\Compiler;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\DependencyInjection\Alias;
use Symfony\Component\DependencyInjection\Loader\YamlFileLoader;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\DependencyInjection\ContainerBuilder;
@ -114,4 +116,79 @@ class IntegrationTest extends TestCase
$this->assertFalse($container->hasDefinition('b'));
$this->assertFalse($container->hasDefinition('c'), 'Service C was not inlined.');
}
public function testInstanceofDefaultsAndParentDefinitionResolution()
{
$container = new ContainerBuilder();
$container->setResourceTracking(false);
// loading YAML with an expressive test-case in that file
$loader = new YamlFileLoader($container, new FileLocator(__DIR__.'/../Fixtures/yaml'));
$loader->load('services_defaults_instanceof_parent.yml');
$container->compile();
// instanceof overrides defaults
$simpleService = $container->getDefinition('service_simple');
$this->assertFalse($simpleService->isAutowired());
$this->assertFalse($simpleService->isShared());
// all tags are kept
$this->assertEquals(
array(
'foo_tag' => array(array('priority' => 100), array()),
'bar_tag' => array(array()),
),
$simpleService->getTags()
);
// calls are all kept, but service-level calls are last
$this->assertEquals(
array(
// from instanceof
array('setSunshine', array('bright')),
// from service
array('enableSummer', array(true)),
array('setSunshine', array('warm')),
),
$simpleService->getMethodCalls()
);
// service override instanceof
$overrideService = $container->getDefinition('service_override_instanceof');
$this->assertTrue($overrideService->isAutowired());
// children definitions get no instanceof
$childDef = $container->getDefinition('child_service');
$this->assertEmpty($childDef->getTags());
$childDef2 = $container->getDefinition('child_service_with_parent_instanceof');
// taken from instanceof applied to parent
$this->assertFalse($childDef2->isAutowired());
// override the instanceof
$this->assertTrue($childDef2->isShared());
// tags inherit like normal
$this->assertEquals(
array(
'foo_tag' => array(array('priority' => 100), array()),
'bar_tag' => array(array()),
),
$simpleService->getTags()
);
}
}
class IntegrationTestStub extends IntegrationTestStubParent
{
}
class IntegrationTestStubParent
{
public function enableSummer($enable)
{
// methods used in calls - added here to prevent errors for not existing
}
public function setSunshine($type)
{
}
}

View File

@ -0,0 +1,49 @@
services:
_defaults:
autowire: true
_instanceof:
Symfony\Component\DependencyInjection\Tests\Compiler\IntegrationTestStubParent:
# should override _defaults
autowire: false
shared: false
tags:
- { name: foo_tag }
calls:
- [setSunshine, [bright]]
# a second instanceof that will be applied
Symfony\Component\DependencyInjection\Tests\Compiler\IntegrationTestStub:
tags:
- { name: bar_tag }
service_simple:
class: Symfony\Component\DependencyInjection\Tests\Compiler\IntegrationTestStub
tags:
- { name: foo_tag, priority: 100 }
# calls from instanceof are kept, but this comes later
calls:
- [enableSummer, [true]]
- [setSunshine, [warm]]
service_override_instanceof:
class: Symfony\Component\DependencyInjection\Tests\Compiler\IntegrationTestStub
# override instanceof
autowire: true
parent_service:
abstract: true
lazy: true
# instanceof will not be applied to this
child_service:
class: Symfony\Component\DependencyInjection\Tests\Compiler\IntegrationTestStub
parent: parent_service
parent_service_with_class:
abstract: true
class: Symfony\Component\DependencyInjection\Tests\Compiler\IntegrationTestStub
child_service_with_parent_instanceof:
parent: parent_service_with_class
shared: true