1102 lines
46 KiB
PHP
Executable File
1102 lines
46 KiB
PHP
Executable File
<?php
|
|
|
|
/*
|
|
* This file is part of the Symfony package.
|
|
*
|
|
* (c) Fabien Potencier <fabien@symfony.com>
|
|
*
|
|
* For the full copyright and license information, please view the LICENSE
|
|
* file that was distributed with this source code.
|
|
*/
|
|
|
|
namespace Symfony\Component\DependencyInjection\Tests\Compiler;
|
|
|
|
use PHPUnit\Framework\TestCase;
|
|
use Psr\Log\LoggerInterface;
|
|
use Psr\Log\NullLogger;
|
|
use Symfony\Component\Config\FileLocator;
|
|
use Symfony\Component\DependencyInjection\Compiler\AutowirePass;
|
|
use Symfony\Component\DependencyInjection\Compiler\AutowireRequiredMethodsPass;
|
|
use Symfony\Component\DependencyInjection\Compiler\DecoratorServicePass;
|
|
use Symfony\Component\DependencyInjection\Compiler\ResolveClassPass;
|
|
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
|
use Symfony\Component\DependencyInjection\Exception\AutowiringFailedException;
|
|
use Symfony\Component\DependencyInjection\Exception\RuntimeException;
|
|
use Symfony\Component\DependencyInjection\Loader\XmlFileLoader;
|
|
use Symfony\Component\DependencyInjection\Reference;
|
|
use Symfony\Component\DependencyInjection\Tests\Fixtures\CaseSensitiveClass;
|
|
use Symfony\Component\DependencyInjection\Tests\Fixtures\includes\FooVariadic;
|
|
use Symfony\Component\DependencyInjection\Tests\Fixtures\includes\MultipleArgumentsOptionalScalarNotReallyOptional;
|
|
use Symfony\Component\DependencyInjection\TypedReference;
|
|
|
|
require_once __DIR__.'/../Fixtures/includes/autowiring_classes.php';
|
|
|
|
/**
|
|
* @author Kévin Dunglas <dunglas@gmail.com>
|
|
*/
|
|
class AutowirePassTest extends TestCase
|
|
{
|
|
public function testProcess()
|
|
{
|
|
$container = new ContainerBuilder();
|
|
|
|
$container->register(Foo::class);
|
|
$barDefinition = $container->register('bar', Bar::class);
|
|
$barDefinition->setAutowired(true);
|
|
|
|
(new ResolveClassPass())->process($container);
|
|
(new AutowirePass())->process($container);
|
|
|
|
$this->assertCount(1, $container->getDefinition('bar')->getArguments());
|
|
$this->assertEquals(Foo::class, (string) $container->getDefinition('bar')->getArgument(0));
|
|
}
|
|
|
|
public function testProcessNotExistingActionParam()
|
|
{
|
|
$container = new ContainerBuilder();
|
|
|
|
$container->register(Foo::class);
|
|
$barDefinition = $container->register(ElsaAction::class, ElsaAction::class);
|
|
$barDefinition->setAutowired(true);
|
|
|
|
(new ResolveClassPass())->process($container);
|
|
try {
|
|
(new AutowirePass())->process($container);
|
|
$this->fail('AutowirePass should have thrown an exception');
|
|
} catch (AutowiringFailedException $e) {
|
|
$this->assertSame('Cannot autowire service "Symfony\Component\DependencyInjection\Tests\Compiler\ElsaAction": argument "$notExisting" of method "__construct()" has type "Symfony\Component\DependencyInjection\Tests\Compiler\NotExisting" but this class was not found.', (string) $e->getMessage());
|
|
}
|
|
}
|
|
|
|
public function testProcessVariadic()
|
|
{
|
|
$container = new ContainerBuilder();
|
|
$container->register(Foo::class);
|
|
$definition = $container->register('fooVariadic', FooVariadic::class);
|
|
$definition->setAutowired(true);
|
|
|
|
(new ResolveClassPass())->process($container);
|
|
(new AutowirePass())->process($container);
|
|
|
|
$this->assertCount(1, $container->getDefinition('fooVariadic')->getArguments());
|
|
$this->assertEquals(Foo::class, (string) $container->getDefinition('fooVariadic')->getArgument(0));
|
|
}
|
|
|
|
public function testProcessAutowireParent()
|
|
{
|
|
$container = new ContainerBuilder();
|
|
|
|
$container->register(B::class);
|
|
$cDefinition = $container->register('c', C::class);
|
|
$cDefinition->setAutowired(true);
|
|
|
|
(new ResolveClassPass())->process($container);
|
|
try {
|
|
(new AutowirePass())->process($container);
|
|
$this->fail('AutowirePass should have thrown an exception');
|
|
} catch (AutowiringFailedException $e) {
|
|
$this->assertSame('Cannot autowire service "c": argument "$a" of method "Symfony\Component\DependencyInjection\Tests\Compiler\C::__construct()" references class "Symfony\Component\DependencyInjection\Tests\Compiler\A" but no such service exists. You should maybe alias this class to the existing "Symfony\Component\DependencyInjection\Tests\Compiler\B" service.', (string) $e->getMessage());
|
|
}
|
|
}
|
|
|
|
public function testProcessAutowireInterface()
|
|
{
|
|
$container = new ContainerBuilder();
|
|
|
|
$container->register(F::class);
|
|
$gDefinition = $container->register('g', G::class);
|
|
$gDefinition->setAutowired(true);
|
|
|
|
(new ResolveClassPass())->process($container);
|
|
try {
|
|
(new AutowirePass())->process($container);
|
|
$this->fail('AutowirePass should have thrown an exception');
|
|
} catch (AutowiringFailedException $e) {
|
|
$this->assertSame('Cannot autowire service "g": argument "$d" of method "Symfony\Component\DependencyInjection\Tests\Compiler\G::__construct()" references interface "Symfony\Component\DependencyInjection\Tests\Compiler\DInterface" but no such service exists. You should maybe alias this interface to the existing "Symfony\Component\DependencyInjection\Tests\Compiler\F" service.', (string) $e->getMessage());
|
|
}
|
|
}
|
|
|
|
public function testCompleteExistingDefinition()
|
|
{
|
|
$container = new ContainerBuilder();
|
|
|
|
$container->register('b', B::class);
|
|
$container->register(DInterface::class, F::class);
|
|
$hDefinition = $container->register('h', H::class)->addArgument(new Reference('b'));
|
|
$hDefinition->setAutowired(true);
|
|
|
|
(new ResolveClassPass())->process($container);
|
|
(new AutowirePass())->process($container);
|
|
|
|
$this->assertCount(2, $container->getDefinition('h')->getArguments());
|
|
$this->assertEquals('b', (string) $container->getDefinition('h')->getArgument(0));
|
|
$this->assertEquals(DInterface::class, (string) $container->getDefinition('h')->getArgument(1));
|
|
}
|
|
|
|
public function testCompleteExistingDefinitionWithNotDefinedArguments()
|
|
{
|
|
$container = new ContainerBuilder();
|
|
|
|
$container->register(B::class);
|
|
$container->register(DInterface::class, F::class);
|
|
$hDefinition = $container->register('h', H::class)->addArgument('')->addArgument('');
|
|
$hDefinition->setAutowired(true);
|
|
|
|
(new ResolveClassPass())->process($container);
|
|
(new AutowirePass())->process($container);
|
|
|
|
$this->assertCount(2, $container->getDefinition('h')->getArguments());
|
|
$this->assertEquals(B::class, (string) $container->getDefinition('h')->getArgument(0));
|
|
$this->assertEquals(DInterface::class, (string) $container->getDefinition('h')->getArgument(1));
|
|
}
|
|
|
|
public function testPrivateConstructorThrowsAutowireException()
|
|
{
|
|
$container = new ContainerBuilder();
|
|
|
|
$container->autowire('private_service', PrivateConstructor::class);
|
|
|
|
$pass = new AutowirePass(true);
|
|
try {
|
|
$pass->process($container);
|
|
$this->fail('AutowirePass should have thrown an exception');
|
|
} catch (AutowiringFailedException $e) {
|
|
$this->assertSame('Invalid service "private_service": constructor of class "Symfony\Component\DependencyInjection\Tests\Compiler\PrivateConstructor" must be public.', (string) $e->getMessage());
|
|
}
|
|
}
|
|
|
|
public function testTypeCollision()
|
|
{
|
|
$container = new ContainerBuilder();
|
|
|
|
$container->register('c1', CollisionA::class);
|
|
$container->register('c2', CollisionB::class);
|
|
$container->register('c3', CollisionB::class);
|
|
$aDefinition = $container->register('a', CannotBeAutowired::class);
|
|
$aDefinition->setAutowired(true);
|
|
|
|
$pass = new AutowirePass();
|
|
try {
|
|
$pass->process($container);
|
|
$this->fail('AutowirePass should have thrown an exception');
|
|
} catch (AutowiringFailedException $e) {
|
|
$this->assertSame('Cannot autowire service "a": argument "$collision" of method "Symfony\Component\DependencyInjection\Tests\Compiler\CannotBeAutowired::__construct()" references interface "Symfony\Component\DependencyInjection\Tests\Compiler\CollisionInterface" but no such service exists. You should maybe alias this interface to one of these existing services: "c1", "c2", "c3".', (string) $e->getMessage());
|
|
}
|
|
}
|
|
|
|
public function testTypeNotGuessable()
|
|
{
|
|
$container = new ContainerBuilder();
|
|
|
|
$container->register('a1', Foo::class);
|
|
$container->register('a2', Foo::class);
|
|
$aDefinition = $container->register('a', NotGuessableArgument::class);
|
|
$aDefinition->setAutowired(true);
|
|
|
|
$pass = new AutowirePass();
|
|
try {
|
|
$pass->process($container);
|
|
$this->fail('AutowirePass should have thrown an exception');
|
|
} catch (AutowiringFailedException $e) {
|
|
$this->assertSame('Cannot autowire service "a": argument "$k" of method "Symfony\Component\DependencyInjection\Tests\Compiler\NotGuessableArgument::__construct()" references class "Symfony\Component\DependencyInjection\Tests\Compiler\Foo" but no such service exists. You should maybe alias this class to one of these existing services: "a1", "a2".', (string) $e->getMessage());
|
|
}
|
|
}
|
|
|
|
public function testTypeNotGuessableWithSubclass()
|
|
{
|
|
$container = new ContainerBuilder();
|
|
|
|
$container->register('a1', B::class);
|
|
$container->register('a2', B::class);
|
|
$aDefinition = $container->register('a', NotGuessableArgumentForSubclass::class);
|
|
$aDefinition->setAutowired(true);
|
|
|
|
$pass = new AutowirePass();
|
|
try {
|
|
$pass->process($container);
|
|
$this->fail('AutowirePass should have thrown an exception');
|
|
} catch (AutowiringFailedException $e) {
|
|
$this->assertSame('Cannot autowire service "a": argument "$k" of method "Symfony\Component\DependencyInjection\Tests\Compiler\NotGuessableArgumentForSubclass::__construct()" references class "Symfony\Component\DependencyInjection\Tests\Compiler\A" but no such service exists. You should maybe alias this class to one of these existing services: "a1", "a2".', (string) $e->getMessage());
|
|
}
|
|
}
|
|
|
|
public function testTypeNotGuessableNoServicesFound()
|
|
{
|
|
$container = new ContainerBuilder();
|
|
|
|
$aDefinition = $container->register('a', CannotBeAutowired::class);
|
|
$aDefinition->setAutowired(true);
|
|
|
|
$pass = new AutowirePass();
|
|
try {
|
|
$pass->process($container);
|
|
$this->fail('AutowirePass should have thrown an exception');
|
|
} catch (AutowiringFailedException $e) {
|
|
$this->assertSame('Cannot autowire service "a": argument "$collision" of method "Symfony\Component\DependencyInjection\Tests\Compiler\CannotBeAutowired::__construct()" references interface "Symfony\Component\DependencyInjection\Tests\Compiler\CollisionInterface" but no such service exists. Did you create a class that implements this interface?', (string) $e->getMessage());
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @requires PHP 8
|
|
*/
|
|
public function testTypeNotGuessableUnionType()
|
|
{
|
|
$container = new ContainerBuilder();
|
|
|
|
$container->register(CollisionA::class);
|
|
$container->register(CollisionB::class);
|
|
|
|
$aDefinition = $container->register('a', UnionClasses::class);
|
|
$aDefinition->setAutowired(true);
|
|
|
|
$pass = new AutowirePass();
|
|
|
|
$this->expectException(AutowiringFailedException::class);
|
|
$this->expectExceptionMessage('Cannot autowire service "a": argument "$collision" of method "Symfony\Component\DependencyInjection\Tests\Compiler\UnionClasses::__construct()" has type "Symfony\Component\DependencyInjection\Tests\Compiler\CollisionA|Symfony\Component\DependencyInjection\Tests\Compiler\CollisionB" but this class was not found.');
|
|
$pass->process($container);
|
|
}
|
|
|
|
/**
|
|
* @requires PHP 8.1
|
|
*/
|
|
public function testTypeNotGuessableIntersectionType()
|
|
{
|
|
$container = new ContainerBuilder();
|
|
|
|
$container->register(CollisionInterface::class);
|
|
$container->register(AnotherInterface::class);
|
|
|
|
$aDefinition = $container->register('a', IntersectionClasses::class);
|
|
$aDefinition->setAutowired(true);
|
|
|
|
$pass = new AutowirePass();
|
|
|
|
$this->expectException(AutowiringFailedException::class);
|
|
$this->expectExceptionMessage('Cannot autowire service "a": argument "$collision" of method "Symfony\Component\DependencyInjection\Tests\Compiler\IntersectionClasses::__construct()" has type "Symfony\Component\DependencyInjection\Tests\Compiler\CollisionInterface&Symfony\Component\DependencyInjection\Tests\Compiler\AnotherInterface" but this class was not found.');
|
|
$pass->process($container);
|
|
}
|
|
|
|
/**
|
|
* @requires PHP 8.2
|
|
*/
|
|
public function testTypeNotGuessableCompositeType()
|
|
{
|
|
$container = new ContainerBuilder();
|
|
|
|
$container->register(CollisionInterface::class);
|
|
$container->register(AnotherInterface::class);
|
|
|
|
$aDefinition = $container->register('a', CompositeTypeClasses::class);
|
|
$aDefinition->setAutowired(true);
|
|
|
|
$pass = new AutowirePass();
|
|
|
|
$this->expectException(AutowiringFailedException::class);
|
|
$this->expectExceptionMessage('Cannot autowire service "a": argument "$collision" of method "Symfony\Component\DependencyInjection\Tests\Compiler\CompositeTypeClasses::__construct()" has type "(Symfony\Component\DependencyInjection\Tests\Compiler\CollisionInterface&Symfony\Component\DependencyInjection\Tests\Compiler\AnotherInterface)|Symfony\Component\DependencyInjection\Tests\Compiler\YetAnotherInterface" but this class was not found.');
|
|
$pass->process($container);
|
|
}
|
|
|
|
public function testTypeNotGuessableWithTypeSet()
|
|
{
|
|
$container = new ContainerBuilder();
|
|
|
|
$container->register('a1', Foo::class);
|
|
$container->register('a2', Foo::class);
|
|
$container->register(Foo::class, Foo::class);
|
|
$aDefinition = $container->register('a', NotGuessableArgument::class);
|
|
$aDefinition->setAutowired(true);
|
|
|
|
$pass = new AutowirePass();
|
|
$pass->process($container);
|
|
|
|
$this->assertCount(1, $container->getDefinition('a')->getArguments());
|
|
$this->assertEquals(Foo::class, (string) $container->getDefinition('a')->getArgument(0));
|
|
}
|
|
|
|
public function testWithTypeSet()
|
|
{
|
|
$container = new ContainerBuilder();
|
|
|
|
$container->register('c1', CollisionA::class);
|
|
$container->register('c2', CollisionB::class);
|
|
$container->setAlias(CollisionInterface::class, 'c2');
|
|
$aDefinition = $container->register('a', CannotBeAutowired::class);
|
|
$aDefinition->setAutowired(true);
|
|
|
|
$pass = new AutowirePass();
|
|
$pass->process($container);
|
|
|
|
$this->assertCount(1, $container->getDefinition('a')->getArguments());
|
|
$this->assertEquals(CollisionInterface::class, (string) $container->getDefinition('a')->getArgument(0));
|
|
}
|
|
|
|
public function testServicesAreNotAutoCreated()
|
|
{
|
|
$container = new ContainerBuilder();
|
|
|
|
$coopTilleulsDefinition = $container->register('coop_tilleuls', LesTilleuls::class);
|
|
$coopTilleulsDefinition->setAutowired(true);
|
|
|
|
$pass = new AutowirePass();
|
|
try {
|
|
$pass->process($container);
|
|
$this->fail('AutowirePass should have thrown an exception');
|
|
} catch (AutowiringFailedException $e) {
|
|
$this->assertSame('Cannot autowire service "coop_tilleuls": argument "$j" of method "Symfony\Component\DependencyInjection\Tests\Compiler\LesTilleuls::__construct()" references class "Symfony\Component\DependencyInjection\Tests\Compiler\Dunglas" but no such service exists.', (string) $e->getMessage());
|
|
}
|
|
}
|
|
|
|
public function testResolveParameter()
|
|
{
|
|
$container = new ContainerBuilder();
|
|
|
|
$container->setParameter('class_name', Bar::class);
|
|
$container->register(Foo::class);
|
|
$barDefinition = $container->register('bar', '%class_name%');
|
|
$barDefinition->setAutowired(true);
|
|
|
|
(new ResolveClassPass())->process($container);
|
|
(new AutowirePass())->process($container);
|
|
|
|
$this->assertEquals(Foo::class, $container->getDefinition('bar')->getArgument(0));
|
|
}
|
|
|
|
public function testOptionalParameter()
|
|
{
|
|
$container = new ContainerBuilder();
|
|
|
|
$container->register(A::class);
|
|
$container->register(Foo::class);
|
|
$optDefinition = $container->register('opt', OptionalParameter::class);
|
|
$optDefinition->setAutowired(true);
|
|
|
|
(new ResolveClassPass())->process($container);
|
|
(new AutowirePass())->process($container);
|
|
|
|
$definition = $container->getDefinition('opt');
|
|
$this->assertNull($definition->getArgument(0));
|
|
$this->assertEquals(A::class, $definition->getArgument(1));
|
|
$this->assertEquals(Foo::class, $definition->getArgument(2));
|
|
}
|
|
|
|
/**
|
|
* @requires PHP 8
|
|
*/
|
|
public function testParameterWithNullUnionIsSkipped()
|
|
{
|
|
$container = new ContainerBuilder();
|
|
|
|
$optDefinition = $container->register('opt', UnionNull::class);
|
|
$optDefinition->setAutowired(true);
|
|
|
|
(new AutowirePass())->process($container);
|
|
|
|
$definition = $container->getDefinition('opt');
|
|
$this->assertNull($definition->getArgument(0));
|
|
}
|
|
|
|
/**
|
|
* @requires PHP 8.2
|
|
*/
|
|
public function testParameterWithNullableIntersectionIsSkipped()
|
|
{
|
|
$container = new ContainerBuilder();
|
|
|
|
$optDefinition = $container->register('opt', NullableIntersection::class);
|
|
$optDefinition->setAutowired(true);
|
|
|
|
(new AutowirePass())->process($container);
|
|
|
|
$definition = $container->getDefinition('opt');
|
|
$this->assertNull($definition->getArgument(0));
|
|
}
|
|
|
|
/**
|
|
* @requires PHP 8
|
|
*/
|
|
public function testParameterWithNullUnionIsAutowired()
|
|
{
|
|
$container = new ContainerBuilder();
|
|
|
|
$container->register(CollisionInterface::class, CollisionA::class);
|
|
|
|
$optDefinition = $container->register('opt', UnionNull::class);
|
|
$optDefinition->setAutowired(true);
|
|
|
|
(new AutowirePass())->process($container);
|
|
|
|
$definition = $container->getDefinition('opt');
|
|
$this->assertEquals(CollisionInterface::class, $definition->getArgument(0));
|
|
}
|
|
|
|
public function testDontTriggerAutowiring()
|
|
{
|
|
$container = new ContainerBuilder();
|
|
|
|
$container->register(Foo::class);
|
|
$container->register('bar', Bar::class);
|
|
|
|
(new ResolveClassPass())->process($container);
|
|
(new AutowirePass())->process($container);
|
|
|
|
$this->assertCount(0, $container->getDefinition('bar')->getArguments());
|
|
}
|
|
|
|
public function testClassNotFoundThrowsException()
|
|
{
|
|
$container = new ContainerBuilder();
|
|
|
|
$aDefinition = $container->register('a', BadTypeHintedArgument::class);
|
|
$aDefinition->setAutowired(true);
|
|
|
|
$container->register(Dunglas::class, Dunglas::class);
|
|
|
|
$pass = new AutowirePass();
|
|
try {
|
|
$pass->process($container);
|
|
$this->fail('AutowirePass should have thrown an exception');
|
|
} catch (AutowiringFailedException $e) {
|
|
$this->assertSame('Cannot autowire service "a": argument "$r" of method "Symfony\Component\DependencyInjection\Tests\Compiler\BadTypeHintedArgument::__construct()" has type "Symfony\Component\DependencyInjection\Tests\Compiler\NotARealClass" but this class was not found.', (string) $e->getMessage());
|
|
}
|
|
}
|
|
|
|
public function testParentClassNotFoundThrowsException()
|
|
{
|
|
$container = new ContainerBuilder();
|
|
|
|
$aDefinition = $container->register('a', BadParentTypeHintedArgument::class);
|
|
$aDefinition->setAutowired(true);
|
|
|
|
$container->register(Dunglas::class, Dunglas::class);
|
|
|
|
$pass = new AutowirePass();
|
|
try {
|
|
$pass->process($container);
|
|
$this->fail('AutowirePass should have thrown an exception');
|
|
} catch (AutowiringFailedException $e) {
|
|
$this->assertMatchesRegularExpression('{^Cannot autowire service "a": argument "\$r" of method "(Symfony\\\\Component\\\\DependencyInjection\\\\Tests\\\\Compiler\\\\)BadParentTypeHintedArgument::__construct\(\)" has type "\1OptionalServiceClass" but this class is missing a parent class \(Class "?Symfony\\\\Bug\\\\NotExistClass"? not found}', (string) $e->getMessage());
|
|
}
|
|
}
|
|
|
|
public function testDontUseAbstractServices()
|
|
{
|
|
$container = new ContainerBuilder();
|
|
|
|
$container->register(Foo::class)->setAbstract(true);
|
|
$container->register('foo', Foo::class);
|
|
$container->register('bar', Bar::class)->setAutowired(true);
|
|
|
|
(new ResolveClassPass())->process($container);
|
|
try {
|
|
(new AutowirePass())->process($container);
|
|
$this->fail('AutowirePass should have thrown an exception');
|
|
} catch (AutowiringFailedException $e) {
|
|
$this->assertSame('Cannot autowire service "bar": argument "$foo" of method "Symfony\Component\DependencyInjection\Tests\Compiler\Bar::__construct()" references class "Symfony\Component\DependencyInjection\Tests\Compiler\Foo" but this service is abstract. You should maybe alias this class to the existing "foo" service.', (string) $e->getMessage());
|
|
}
|
|
}
|
|
|
|
public function testSomeSpecificArgumentsAreSet()
|
|
{
|
|
$container = new ContainerBuilder();
|
|
|
|
$container->register('foo', Foo::class);
|
|
$container->register(A::class);
|
|
$container->register(Dunglas::class);
|
|
$container->register('multiple', MultipleArguments::class)
|
|
->setAutowired(true)
|
|
// set the 2nd (index 1) argument only: autowire the first and third
|
|
// args are: A, Foo, Dunglas
|
|
->setArguments([
|
|
1 => new Reference('foo'),
|
|
3 => ['bar'],
|
|
]);
|
|
|
|
(new ResolveClassPass())->process($container);
|
|
(new AutowirePass())->process($container);
|
|
|
|
$definition = $container->getDefinition('multiple');
|
|
$this->assertEquals(
|
|
[
|
|
new TypedReference(A::class, A::class),
|
|
new Reference('foo'),
|
|
new TypedReference(Dunglas::class, Dunglas::class),
|
|
['bar'],
|
|
],
|
|
$definition->getArguments()
|
|
);
|
|
}
|
|
|
|
public function testScalarArgsCannotBeAutowired()
|
|
{
|
|
$container = new ContainerBuilder();
|
|
|
|
$container->register(A::class);
|
|
$container->register(Dunglas::class);
|
|
$container->register('arg_no_type_hint', MultipleArguments::class)
|
|
->setArguments([1 => 'foo'])
|
|
->setAutowired(true);
|
|
|
|
(new ResolveClassPass())->process($container);
|
|
try {
|
|
(new AutowirePass())->process($container);
|
|
$this->fail('AutowirePass should have thrown an exception');
|
|
} catch (AutowiringFailedException $e) {
|
|
$this->assertSame('Cannot autowire service "arg_no_type_hint": argument "$bar" of method "Symfony\Component\DependencyInjection\Tests\Compiler\MultipleArguments::__construct()" is type-hinted "array", you should configure its value explicitly.', (string) $e->getMessage());
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @requires PHP 8
|
|
*/
|
|
public function testUnionScalarArgsCannotBeAutowired()
|
|
{
|
|
$this->expectException(AutowiringFailedException::class);
|
|
$this->expectExceptionMessage('Cannot autowire service "union_scalars": argument "$timeout" of method "Symfony\Component\DependencyInjection\Tests\Compiler\UnionScalars::__construct()" is type-hinted "int|float", you should configure its value explicitly.');
|
|
$container = new ContainerBuilder();
|
|
|
|
$container->register('union_scalars', UnionScalars::class)
|
|
->setAutowired(true);
|
|
|
|
(new AutowirePass())->process($container);
|
|
}
|
|
|
|
public function testNoTypeArgsCannotBeAutowired()
|
|
{
|
|
$container = new ContainerBuilder();
|
|
|
|
$container->register(A::class);
|
|
$container->register(Dunglas::class);
|
|
$container->register('arg_no_type_hint', MultipleArguments::class)
|
|
->setAutowired(true);
|
|
|
|
(new ResolveClassPass())->process($container);
|
|
try {
|
|
(new AutowirePass())->process($container);
|
|
$this->fail('AutowirePass should have thrown an exception');
|
|
} catch (AutowiringFailedException $e) {
|
|
$this->assertSame('Cannot autowire service "arg_no_type_hint": argument "$foo" of method "Symfony\Component\DependencyInjection\Tests\Compiler\MultipleArguments::__construct()" has no type-hint, you should configure its value explicitly.', (string) $e->getMessage());
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @requires PHP < 8
|
|
*/
|
|
public function testOptionalScalarNotReallyOptionalUsesDefaultValue()
|
|
{
|
|
$container = new ContainerBuilder();
|
|
|
|
$container->register(A::class);
|
|
$container->register(Lille::class);
|
|
$definition = $container->register('not_really_optional_scalar', MultipleArgumentsOptionalScalarNotReallyOptional::class)
|
|
->setAutowired(true);
|
|
|
|
(new ResolveClassPass())->process($container);
|
|
(new AutowirePass())->process($container);
|
|
|
|
$this->assertSame('default_val', $definition->getArgument(1));
|
|
}
|
|
|
|
public function testOptionalScalarArgsDontMessUpOrder()
|
|
{
|
|
$container = new ContainerBuilder();
|
|
|
|
$container->register(A::class);
|
|
$container->register(Lille::class);
|
|
$container->register('with_optional_scalar', MultipleArgumentsOptionalScalar::class)
|
|
->setAutowired(true);
|
|
|
|
(new ResolveClassPass())->process($container);
|
|
(new AutowirePass())->process($container);
|
|
|
|
$definition = $container->getDefinition('with_optional_scalar');
|
|
$this->assertEquals(
|
|
[
|
|
new TypedReference(A::class, A::class),
|
|
// use the default value
|
|
'default_val',
|
|
new TypedReference(Lille::class, Lille::class),
|
|
],
|
|
$definition->getArguments()
|
|
);
|
|
}
|
|
|
|
public function testOptionalScalarArgsNotPassedIfLast()
|
|
{
|
|
$container = new ContainerBuilder();
|
|
|
|
$container->register(A::class);
|
|
$container->register(Lille::class);
|
|
$container->register('with_optional_scalar_last', MultipleArgumentsOptionalScalarLast::class)
|
|
->setAutowired(true);
|
|
|
|
(new ResolveClassPass())->process($container);
|
|
(new AutowirePass())->process($container);
|
|
|
|
$definition = $container->getDefinition('with_optional_scalar_last');
|
|
$this->assertEquals(
|
|
[
|
|
new TypedReference(A::class, A::class),
|
|
new TypedReference(Lille::class, Lille::class),
|
|
],
|
|
$definition->getArguments()
|
|
);
|
|
}
|
|
|
|
public function testOptionalArgsNoRequiredForCoreClasses()
|
|
{
|
|
$container = new ContainerBuilder();
|
|
|
|
$container->register('foo', \SplFileObject::class)
|
|
->addArgument('foo.txt')
|
|
->setAutowired(true);
|
|
|
|
(new AutowirePass())->process($container);
|
|
|
|
$definition = $container->getDefinition('foo');
|
|
$this->assertEquals(
|
|
['foo.txt'],
|
|
$definition->getArguments()
|
|
);
|
|
}
|
|
|
|
public function testSetterInjection()
|
|
{
|
|
$container = new ContainerBuilder();
|
|
$container->register(Foo::class);
|
|
$container->register(A::class);
|
|
$container->register(CollisionA::class);
|
|
$container->register(CollisionB::class);
|
|
|
|
// manually configure *one* call, to override autowiring
|
|
$container
|
|
->register('setter_injection', SetterInjection::class)
|
|
->setAutowired(true)
|
|
->addMethodCall('setWithCallsConfigured', ['manual_arg1', 'manual_arg2'])
|
|
;
|
|
|
|
(new ResolveClassPass())->process($container);
|
|
(new AutowireRequiredMethodsPass())->process($container);
|
|
(new AutowirePass())->process($container);
|
|
|
|
$methodCalls = $container->getDefinition('setter_injection')->getMethodCalls();
|
|
|
|
$this->assertEquals(
|
|
['setWithCallsConfigured', 'setFoo', 'setDependencies', 'setChildMethodWithoutDocBlock'],
|
|
array_column($methodCalls, 0)
|
|
);
|
|
|
|
// test setWithCallsConfigured args
|
|
$this->assertEquals(
|
|
['manual_arg1', 'manual_arg2'],
|
|
$methodCalls[0][1]
|
|
);
|
|
// test setFoo args
|
|
$this->assertEquals(
|
|
[new TypedReference(Foo::class, Foo::class)],
|
|
$methodCalls[1][1]
|
|
);
|
|
}
|
|
|
|
public function testWithNonExistingSetterAndAutowiring()
|
|
{
|
|
$this->expectException(RuntimeException::class);
|
|
$this->expectExceptionMessage('Invalid service "Symfony\Component\DependencyInjection\Tests\Fixtures\CaseSensitiveClass": method "setLogger()" does not exist.');
|
|
$container = new ContainerBuilder();
|
|
|
|
$definition = $container->register(CaseSensitiveClass::class, CaseSensitiveClass::class)->setAutowired(true);
|
|
$definition->addMethodCall('setLogger');
|
|
|
|
(new ResolveClassPass())->process($container);
|
|
(new AutowireRequiredMethodsPass())->process($container);
|
|
(new AutowirePass())->process($container);
|
|
}
|
|
|
|
public function testExplicitMethodInjection()
|
|
{
|
|
$container = new ContainerBuilder();
|
|
$container->register(Foo::class);
|
|
$container->register(A::class);
|
|
$container->register(CollisionA::class);
|
|
$container->register(CollisionB::class);
|
|
|
|
$container
|
|
->register('setter_injection', SetterInjection::class)
|
|
->setAutowired(true)
|
|
->addMethodCall('notASetter', [])
|
|
;
|
|
|
|
(new ResolveClassPass())->process($container);
|
|
(new AutowireRequiredMethodsPass())->process($container);
|
|
(new AutowirePass())->process($container);
|
|
|
|
$methodCalls = $container->getDefinition('setter_injection')->getMethodCalls();
|
|
|
|
$this->assertEquals(
|
|
['notASetter', 'setFoo', 'setDependencies', 'setWithCallsConfigured', 'setChildMethodWithoutDocBlock'],
|
|
array_column($methodCalls, 0)
|
|
);
|
|
$this->assertEquals(
|
|
[new TypedReference(A::class, A::class)],
|
|
$methodCalls[0][1]
|
|
);
|
|
}
|
|
|
|
public function getCreateResourceTests()
|
|
{
|
|
return [
|
|
['IdenticalClassResource', true],
|
|
['ClassChangedConstructorArgs', false],
|
|
];
|
|
}
|
|
|
|
public function testIgnoreServiceWithClassNotExisting()
|
|
{
|
|
$container = new ContainerBuilder();
|
|
|
|
$container->register('class_not_exist', OptionalServiceClass::class);
|
|
|
|
$barDefinition = $container->register('bar', Bar::class);
|
|
$barDefinition->setAutowired(true);
|
|
|
|
$container->register(Foo::class, Foo::class);
|
|
|
|
$pass = new AutowirePass();
|
|
$pass->process($container);
|
|
|
|
$this->assertTrue($container->hasDefinition('bar'));
|
|
}
|
|
|
|
public function testSetterInjectionCollisionThrowsException()
|
|
{
|
|
$container = new ContainerBuilder();
|
|
|
|
$container->register('c1', CollisionA::class);
|
|
$container->register('c2', CollisionB::class);
|
|
$aDefinition = $container->register('setter_injection_collision', SetterInjectionCollision::class);
|
|
$aDefinition->setAutowired(true);
|
|
|
|
(new AutowireRequiredMethodsPass())->process($container);
|
|
|
|
$pass = new AutowirePass();
|
|
|
|
try {
|
|
$pass->process($container);
|
|
$this->fail('AutowirePass should have thrown an exception');
|
|
} catch (AutowiringFailedException $e) {
|
|
$this->assertSame('Cannot autowire service "setter_injection_collision": argument "$collision" of method "Symfony\Component\DependencyInjection\Tests\Compiler\SetterInjectionCollision::setMultipleInstancesForOneArg()" references interface "Symfony\Component\DependencyInjection\Tests\Compiler\CollisionInterface" but no such service exists. You should maybe alias this interface to one of these existing services: "c1", "c2".', (string) $e->getMessage());
|
|
}
|
|
}
|
|
|
|
public function testInterfaceWithNoImplementationSuggestToWriteOne()
|
|
{
|
|
$container = new ContainerBuilder();
|
|
|
|
$aDefinition = $container->register('my_service', K::class);
|
|
$aDefinition->setAutowired(true);
|
|
|
|
(new AutowireRequiredMethodsPass())->process($container);
|
|
|
|
$pass = new AutowirePass();
|
|
try {
|
|
$pass->process($container);
|
|
$this->fail('AutowirePass should have thrown an exception');
|
|
} catch (AutowiringFailedException $e) {
|
|
$this->assertSame('Cannot autowire service "my_service": argument "$i" of method "Symfony\Component\DependencyInjection\Tests\Compiler\K::__construct()" references interface "Symfony\Component\DependencyInjection\Tests\Compiler\IInterface" but no such service exists. Did you create a class that implements this interface?', (string) $e->getMessage());
|
|
}
|
|
}
|
|
|
|
public function testProcessDoesNotTriggerDeprecations()
|
|
{
|
|
$container = new ContainerBuilder();
|
|
$container->register('deprecated', 'Symfony\Component\DependencyInjection\Tests\Fixtures\DeprecatedClass')->setDeprecated(true);
|
|
$container->register('foo', Foo::class);
|
|
$container->register('bar', Bar::class)->setAutowired(true);
|
|
|
|
$pass = new AutowirePass();
|
|
try {
|
|
$pass->process($container);
|
|
$this->fail('AutowirePass should have thrown an exception');
|
|
} catch (AutowiringFailedException $e) {
|
|
$this->assertSame('Cannot autowire service "bar": argument "$foo" of method "Symfony\Component\DependencyInjection\Tests\Compiler\Bar::__construct()" references class "Symfony\Component\DependencyInjection\Tests\Compiler\Foo" but no such service exists. You should maybe alias this class to the existing "foo" service.', (string) $e->getMessage());
|
|
}
|
|
|
|
$this->assertTrue($container->hasDefinition('deprecated'));
|
|
$this->assertTrue($container->hasDefinition('foo'));
|
|
$this->assertTrue($container->hasDefinition('bar'));
|
|
}
|
|
|
|
public function testEmptyStringIsKept()
|
|
{
|
|
$container = new ContainerBuilder();
|
|
|
|
$container->register(A::class);
|
|
$container->register(Lille::class);
|
|
$container->register('foo', MultipleArgumentsOptionalScalar::class)
|
|
->setAutowired(true)
|
|
->setArguments(['', '']);
|
|
|
|
(new ResolveClassPass())->process($container);
|
|
(new AutowirePass())->process($container);
|
|
|
|
$this->assertEquals([new TypedReference(A::class, A::class), '', new TypedReference(Lille::class, Lille::class)], $container->getDefinition('foo')->getArguments());
|
|
}
|
|
|
|
public function testWithFactory()
|
|
{
|
|
$container = new ContainerBuilder();
|
|
|
|
$container->register(Foo::class);
|
|
$definition = $container->register('a', A::class)
|
|
->setFactory([A::class, 'create'])
|
|
->setAutowired(true);
|
|
|
|
(new ResolveClassPass())->process($container);
|
|
(new AutowirePass())->process($container);
|
|
|
|
$this->assertEquals([new TypedReference(Foo::class, Foo::class)], $definition->getArguments());
|
|
}
|
|
|
|
/**
|
|
* @dataProvider provideNotWireableCalls
|
|
*/
|
|
public function testNotWireableCalls($method, $expectedMsg)
|
|
{
|
|
$container = new ContainerBuilder();
|
|
|
|
$foo = $container->register('foo', NotWireable::class)->setAutowired(true)
|
|
->addMethodCall('setBar', [])
|
|
->addMethodCall('setOptionalNotAutowireable', [])
|
|
->addMethodCall('setOptionalNoTypeHint', [])
|
|
->addMethodCall('setOptionalArgNoAutowireable', [])
|
|
;
|
|
|
|
if ($method) {
|
|
$foo->addMethodCall($method, []);
|
|
}
|
|
|
|
(new ResolveClassPass())->process($container);
|
|
(new AutowireRequiredMethodsPass())->process($container);
|
|
try {
|
|
(new AutowirePass())->process($container);
|
|
$this->fail('AutowirePass should throw a RuntimeException.');
|
|
} catch (RuntimeException $e) {
|
|
$this->assertSame($expectedMsg, (string) $e->getMessage());
|
|
}
|
|
}
|
|
|
|
public function provideNotWireableCalls()
|
|
{
|
|
return [
|
|
['setNotAutowireable', 'Cannot autowire service "foo": argument "$n" of method "Symfony\Component\DependencyInjection\Tests\Compiler\NotWireable::setNotAutowireable()" has type "Symfony\Component\DependencyInjection\Tests\Compiler\NotARealClass" but this class was not found.'],
|
|
['setDifferentNamespace', 'Cannot autowire service "foo": argument "$n" of method "Symfony\Component\DependencyInjection\Tests\Compiler\NotWireable::setDifferentNamespace()" references class "stdClass" but no such service exists.'],
|
|
[null, 'Invalid service "foo": method "Symfony\Component\DependencyInjection\Tests\Compiler\NotWireable::setProtectedMethod()" must be public.'],
|
|
];
|
|
}
|
|
|
|
public function testSuggestRegisteredServicesWithSimilarCase()
|
|
{
|
|
$container = new ContainerBuilder();
|
|
|
|
$container->register(LesTilleuls::class, LesTilleuls::class);
|
|
$container->register('foo', NotWireable::class)->setAutowired(true)
|
|
->addMethodCall('setNotAutowireableBecauseOfATypo', [])
|
|
;
|
|
|
|
(new ResolveClassPass())->process($container);
|
|
(new AutowireRequiredMethodsPass())->process($container);
|
|
try {
|
|
(new AutowirePass())->process($container);
|
|
$this->fail('AutowirePass should have thrown an exception');
|
|
} catch (AutowiringFailedException $e) {
|
|
$this->assertSame('Cannot autowire service "foo": argument "$sam" of method "Symfony\Component\DependencyInjection\Tests\Compiler\NotWireable::setNotAutowireableBecauseOfATypo()" references class "Symfony\Component\DependencyInjection\Tests\Compiler\lesTilleuls" but no such service exists. Did you mean "Symfony\Component\DependencyInjection\Tests\Compiler\LesTilleuls"?', (string) $e->getMessage());
|
|
}
|
|
}
|
|
|
|
public function testByIdAlternative()
|
|
{
|
|
$container = new ContainerBuilder();
|
|
|
|
$container->setAlias(IInterface::class, 'i');
|
|
$container->register('i', I::class);
|
|
$container->register('j', J::class)
|
|
->setAutowired(true);
|
|
|
|
$pass = new AutowirePass();
|
|
try {
|
|
$pass->process($container);
|
|
$this->fail('AutowirePass should have thrown an exception');
|
|
} catch (AutowiringFailedException $e) {
|
|
$this->assertSame('Cannot autowire service "j": argument "$i" of method "Symfony\Component\DependencyInjection\Tests\Compiler\J::__construct()" references class "Symfony\Component\DependencyInjection\Tests\Compiler\I" but no such service exists. Try changing the type-hint to "Symfony\Component\DependencyInjection\Tests\Compiler\IInterface" instead.', (string) $e->getMessage());
|
|
}
|
|
}
|
|
|
|
public function testExceptionWhenAliasExists()
|
|
{
|
|
$container = new ContainerBuilder();
|
|
|
|
// multiple I services... but there *is* IInterface available
|
|
$container->setAlias(IInterface::class, 'i');
|
|
$container->register('i', I::class);
|
|
$container->register('i2', I::class);
|
|
// J type-hints against I concretely
|
|
$container->register('j', J::class)
|
|
->setAutowired(true);
|
|
|
|
$pass = new AutowirePass();
|
|
try {
|
|
$pass->process($container);
|
|
$this->fail('AutowirePass should have thrown an exception');
|
|
} catch (AutowiringFailedException $e) {
|
|
$this->assertSame('Cannot autowire service "j": argument "$i" of method "Symfony\Component\DependencyInjection\Tests\Compiler\J::__construct()" references class "Symfony\Component\DependencyInjection\Tests\Compiler\I" but no such service exists. Try changing the type-hint to "Symfony\Component\DependencyInjection\Tests\Compiler\IInterface" instead.', (string) $e->getMessage());
|
|
}
|
|
}
|
|
|
|
public function testExceptionWhenAliasDoesNotExist()
|
|
{
|
|
$container = new ContainerBuilder();
|
|
|
|
// multiple I instances... but no IInterface alias
|
|
$container->register('i', I::class);
|
|
$container->register('i2', I::class);
|
|
// J type-hints against I concretely
|
|
$container->register('j', J::class)
|
|
->setAutowired(true);
|
|
|
|
$pass = new AutowirePass();
|
|
try {
|
|
$pass->process($container);
|
|
$this->fail('AutowirePass should have thrown an exception');
|
|
} catch (AutowiringFailedException $e) {
|
|
$this->assertSame('Cannot autowire service "j": argument "$i" of method "Symfony\Component\DependencyInjection\Tests\Compiler\J::__construct()" references class "Symfony\Component\DependencyInjection\Tests\Compiler\I" but no such service exists. You should maybe alias this class to one of these existing services: "i", "i2".', (string) $e->getMessage());
|
|
}
|
|
}
|
|
|
|
public function testInlineServicesAreNotCandidates()
|
|
{
|
|
$container = new ContainerBuilder();
|
|
$loader = new XmlFileLoader($container, new FileLocator(realpath(__DIR__.'/../Fixtures/xml')));
|
|
$loader->load('services_inline_not_candidate.xml');
|
|
|
|
$pass = new AutowirePass();
|
|
$pass->process($container);
|
|
|
|
$this->assertSame([], $container->getDefinition('autowired')->getArguments());
|
|
}
|
|
|
|
public function testAutowireDecorator()
|
|
{
|
|
$container = new ContainerBuilder();
|
|
$container->register(LoggerInterface::class, NullLogger::class);
|
|
$container->register(Decorated::class, Decorated::class);
|
|
$container
|
|
->register(Decorator::class, Decorator::class)
|
|
->setDecoratedService(Decorated::class)
|
|
->setAutowired(true)
|
|
;
|
|
|
|
(new DecoratorServicePass())->process($container);
|
|
(new AutowirePass())->process($container);
|
|
|
|
$definition = $container->getDefinition(Decorator::class);
|
|
$this->assertSame(Decorator::class.'.inner', (string) $definition->getArgument(1));
|
|
}
|
|
|
|
public function testAutowireDecoratorChain()
|
|
{
|
|
$container = new ContainerBuilder();
|
|
$container->register(LoggerInterface::class, NullLogger::class);
|
|
$container->register(Decorated::class, Decorated::class);
|
|
$container
|
|
->register(Decorator::class, Decorator::class)
|
|
->setDecoratedService(Decorated::class)
|
|
->setAutowired(true)
|
|
;
|
|
$container
|
|
->register(DecoratedDecorator::class, DecoratedDecorator::class)
|
|
->setDecoratedService(Decorated::class)
|
|
->setAutowired(true)
|
|
;
|
|
|
|
(new DecoratorServicePass())->process($container);
|
|
(new AutowirePass())->process($container);
|
|
|
|
$definition = $container->getDefinition(DecoratedDecorator::class);
|
|
$this->assertSame(DecoratedDecorator::class.'.inner', (string) $definition->getArgument(0));
|
|
}
|
|
|
|
public function testAutowireDecoratorRenamedId()
|
|
{
|
|
$container = new ContainerBuilder();
|
|
$container->register(LoggerInterface::class, NullLogger::class);
|
|
$container->register(Decorated::class, Decorated::class);
|
|
$container
|
|
->register(Decorator::class, Decorator::class)
|
|
->setDecoratedService(Decorated::class, 'renamed')
|
|
->setAutowired(true)
|
|
;
|
|
|
|
(new DecoratorServicePass())->process($container);
|
|
(new AutowirePass())->process($container);
|
|
|
|
$definition = $container->getDefinition(Decorator::class);
|
|
$this->assertSame('renamed', (string) $definition->getArgument(1));
|
|
}
|
|
|
|
public function testDoNotAutowireDecoratorWhenSeveralArgumentOfTheType()
|
|
{
|
|
$container = new ContainerBuilder();
|
|
$container->register(LoggerInterface::class, NullLogger::class);
|
|
$container->register(Decorated::class, Decorated::class);
|
|
$container
|
|
->register(NonAutowirableDecorator::class, NonAutowirableDecorator::class)
|
|
->setDecoratedService(Decorated::class)
|
|
->setAutowired(true)
|
|
;
|
|
|
|
(new DecoratorServicePass())->process($container);
|
|
try {
|
|
(new AutowirePass())->process($container);
|
|
$this->fail('AutowirePass should have thrown an exception');
|
|
} catch (AutowiringFailedException $e) {
|
|
$this->assertSame('Cannot autowire service "Symfony\Component\DependencyInjection\Tests\Compiler\NonAutowirableDecorator": argument "$decorated1" of method "__construct()" references interface "Symfony\Component\DependencyInjection\Tests\Compiler\DecoratorInterface" but no such service exists. You should maybe alias this interface to one of these existing services: "Symfony\Component\DependencyInjection\Tests\Compiler\NonAutowirableDecorator", "Symfony\Component\DependencyInjection\Tests\Compiler\NonAutowirableDecorator.inner".', (string) $e->getMessage());
|
|
}
|
|
}
|
|
|
|
public function testErroredServiceLocator()
|
|
{
|
|
$container = new ContainerBuilder();
|
|
$container->register('some_locator', 'stdClass')
|
|
->addArgument(new TypedReference(MissingClass::class, MissingClass::class, ContainerBuilder::RUNTIME_EXCEPTION_ON_INVALID_REFERENCE))
|
|
->addTag('container.service_locator');
|
|
|
|
(new AutowirePass())->process($container);
|
|
|
|
$this->assertSame(['Cannot autowire service "some_locator": it has type "Symfony\Component\DependencyInjection\Tests\Compiler\MissingClass" but this class was not found.'], $container->getDefinition('.errored.some_locator.'.MissingClass::class)->getErrors());
|
|
}
|
|
|
|
public function testNamedArgumentAliasResolveCollisions()
|
|
{
|
|
$container = new ContainerBuilder();
|
|
|
|
$container->register('c1', CollisionA::class);
|
|
$container->register('c2', CollisionB::class);
|
|
$container->setAlias(CollisionInterface::class.' $collision', 'c2');
|
|
$aDefinition = $container->register('setter_injection_collision', SetterInjectionCollision::class);
|
|
$aDefinition->setAutowired(true);
|
|
|
|
(new AutowireRequiredMethodsPass())->process($container);
|
|
|
|
$pass = new AutowirePass();
|
|
|
|
$pass->process($container);
|
|
|
|
$expected = [
|
|
[
|
|
'setMultipleInstancesForOneArg',
|
|
[new TypedReference(CollisionInterface::class.' $collision', CollisionInterface::class)],
|
|
],
|
|
];
|
|
$this->assertEquals($expected, $container->getDefinition('setter_injection_collision')->getMethodCalls());
|
|
}
|
|
}
|