2015-08-24 02:36:41 +01:00
< ? 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 ;
2017-02-18 17:42:54 +00:00
use PHPUnit\Framework\TestCase ;
2017-10-08 15:29:36 +01:00
use Symfony\Component\Config\FileLocator ;
2015-08-24 02:36:41 +01:00
use Symfony\Component\DependencyInjection\Compiler\AutowirePass ;
2018-07-26 10:06:28 +01:00
use Symfony\Component\DependencyInjection\Compiler\AutowireRequiredMethodsPass ;
2017-04-04 18:35:51 +01:00
use Symfony\Component\DependencyInjection\Compiler\ResolveClassPass ;
2015-08-24 02:36:41 +01:00
use Symfony\Component\DependencyInjection\ContainerBuilder ;
2018-03-19 09:44:01 +00:00
use Symfony\Component\DependencyInjection\Exception\AutowiringFailedException ;
2017-03-17 09:21:51 +00:00
use Symfony\Component\DependencyInjection\Exception\RuntimeException ;
2017-10-08 15:29:36 +01:00
use Symfony\Component\DependencyInjection\Loader\XmlFileLoader ;
2015-08-24 02:36:41 +01:00
use Symfony\Component\DependencyInjection\Reference ;
2017-01-22 14:49:28 +00:00
use Symfony\Component\DependencyInjection\Tests\Fixtures\includes\FooVariadic ;
2017-02-26 17:31:03 +00:00
use Symfony\Component\DependencyInjection\TypedReference ;
2015-08-24 02:36:41 +01:00
2017-09-23 23:04:06 +01:00
require_once __DIR__ . '/../Fixtures/includes/autowiring_classes.php' ;
2015-08-24 02:36:41 +01:00
/**
* @ author Kévin Dunglas < dunglas @ gmail . com >
*/
2017-02-18 17:42:54 +00:00
class AutowirePassTest extends TestCase
2015-08-24 02:36:41 +01:00
{
public function testProcess ()
{
$container = new ContainerBuilder ();
2017-04-04 18:35:51 +01:00
$container -> register ( Foo :: class );
2015-08-24 02:36:41 +01:00
$barDefinition = $container -> register ( 'bar' , __NAMESPACE__ . '\Bar' );
$barDefinition -> setAutowired ( true );
2017-04-04 18:35:51 +01:00
( new ResolveClassPass ()) -> process ( $container );
( new AutowirePass ()) -> process ( $container );
2015-08-24 02:36:41 +01:00
$this -> assertCount ( 1 , $container -> getDefinition ( 'bar' ) -> getArguments ());
2017-04-04 18:35:51 +01:00
$this -> assertEquals ( Foo :: class , ( string ) $container -> getDefinition ( 'bar' ) -> getArgument ( 0 ));
2015-08-24 02:36:41 +01:00
}
2017-01-22 14:49:28 +00:00
/**
* @ requires PHP 5.6
*/
public function testProcessVariadic ()
{
$container = new ContainerBuilder ();
2017-04-04 18:35:51 +01:00
$container -> register ( Foo :: class );
2017-01-22 14:49:28 +00:00
$definition = $container -> register ( 'fooVariadic' , FooVariadic :: class );
$definition -> setAutowired ( true );
2017-04-04 18:35:51 +01:00
( new ResolveClassPass ()) -> process ( $container );
( new AutowirePass ()) -> process ( $container );
2017-01-22 14:49:28 +00:00
$this -> assertCount ( 1 , $container -> getDefinition ( 'fooVariadic' ) -> getArguments ());
2017-04-04 18:35:51 +01:00
$this -> assertEquals ( Foo :: class , ( string ) $container -> getDefinition ( 'fooVariadic' ) -> getArgument ( 0 ));
2017-01-22 14:49:28 +00:00
}
2017-04-04 18:35:51 +01:00
/**
2017-04-11 22:05:55 +01:00
* @ group legacy
* @ expectedDeprecation Autowiring services based on the types they implement is deprecated since Symfony 3.3 and won ' t be supported in version 4.0 . You should alias the " Symfony \ Component \ DependencyInjection \T ests \ Compiler \ B " service to " Symfony \ Component \ DependencyInjection \T ests \ Compiler \ A " instead .
* @ expectedExceptionInSymfony4 \Symfony\Component\DependencyInjection\Exception\RuntimeException
* @ expectedExceptionMessageInSymfony4 Cannot autowire service " c " : argument " $a " of method " Symfony \ Component \ DependencyInjection \T ests \ 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.
2017-04-04 18:35:51 +01:00
*/
2015-08-24 02:36:41 +01:00
public function testProcessAutowireParent ()
{
$container = new ContainerBuilder ();
2017-04-04 18:35:51 +01:00
$container -> register ( B :: class );
2015-08-24 02:36:41 +01:00
$cDefinition = $container -> register ( 'c' , __NAMESPACE__ . '\C' );
$cDefinition -> setAutowired ( true );
2017-04-04 18:35:51 +01:00
( new ResolveClassPass ()) -> process ( $container );
( new AutowirePass ()) -> process ( $container );
2015-08-24 02:36:41 +01:00
$this -> assertCount ( 1 , $container -> getDefinition ( 'c' ) -> getArguments ());
2017-04-04 18:35:51 +01:00
$this -> assertEquals ( B :: class , ( string ) $container -> getDefinition ( 'c' ) -> getArgument ( 0 ));
2015-08-24 02:36:41 +01:00
}
2017-05-05 12:31:04 +01:00
/**
* @ group legacy
* @ expectedDeprecation Autowiring services based on the types they implement is deprecated since Symfony 3.3 and won ' t be supported in version 4.0 . Try changing the type - hint for argument " $a " of method " Symfony \ Component \ DependencyInjection \T ests \ Compiler \ C::__construct() " to " Symfony \ Component \ DependencyInjection \T ests \ Compiler \ AInterface " instead .
* @ expectedExceptionInSymfony4 \Symfony\Component\DependencyInjection\Exception\RuntimeException
* @ expectedExceptionMessageInSymfony4 Cannot autowire service " c " : argument " $a " of method " Symfony \ Component \ DependencyInjection \T ests \ 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.
*/
public function testProcessLegacyAutowireWithAvailableInterface ()
{
$container = new ContainerBuilder ();
$container -> setAlias ( AInterface :: class , B :: class );
$container -> register ( B :: class );
$cDefinition = $container -> register ( 'c' , __NAMESPACE__ . '\C' );
$cDefinition -> setAutowired ( true );
( new ResolveClassPass ()) -> process ( $container );
( new AutowirePass ()) -> process ( $container );
$this -> assertCount ( 1 , $container -> getDefinition ( 'c' ) -> getArguments ());
$this -> assertEquals ( B :: class , ( string ) $container -> getDefinition ( 'c' ) -> getArgument ( 0 ));
}
2017-04-04 18:35:51 +01:00
/**
2017-04-11 22:05:55 +01:00
* @ group legacy
* @ expectedDeprecation Autowiring services based on the types they implement is deprecated since Symfony 3.3 and won ' t be supported in version 4.0 . You should alias the " Symfony \ Component \ DependencyInjection \T ests \ Compiler \ F " service to " Symfony \ Component \ DependencyInjection \T ests \ Compiler \ DInterface " instead .
* @ expectedExceptionInSymfony4 \Symfony\Component\DependencyInjection\Exception\RuntimeException
* @ expectedExceptionMessageInSymfony4 Cannot autowire service " g " : argument " $d " of method " Symfony \ Component \ DependencyInjection \T ests \ Compiler \ G::__construct() " references interface " Symfony \ Component \ DependencyInjection \T ests \ Compiler \ DInterface " but no such service exists . You should maybe alias this interface to the existing " Symfony \ Component \ DependencyInjection \T ests \ Compiler \ F " service .
2017-04-04 18:35:51 +01:00
*/
2015-08-24 02:36:41 +01:00
public function testProcessAutowireInterface ()
{
$container = new ContainerBuilder ();
2017-04-04 18:35:51 +01:00
$container -> register ( F :: class );
2015-08-24 02:36:41 +01:00
$gDefinition = $container -> register ( 'g' , __NAMESPACE__ . '\G' );
$gDefinition -> setAutowired ( true );
2017-04-04 18:35:51 +01:00
( new ResolveClassPass ()) -> process ( $container );
( new AutowirePass ()) -> process ( $container );
2015-08-24 02:36:41 +01:00
2016-02-23 09:13:51 +00:00
$this -> assertCount ( 3 , $container -> getDefinition ( 'g' ) -> getArguments ());
2017-04-04 18:35:51 +01:00
$this -> assertEquals ( F :: class , ( string ) $container -> getDefinition ( 'g' ) -> getArgument ( 0 ));
$this -> assertEquals ( F :: class , ( string ) $container -> getDefinition ( 'g' ) -> getArgument ( 1 ));
$this -> assertEquals ( F :: class , ( string ) $container -> getDefinition ( 'g' ) -> getArgument ( 2 ));
2015-08-24 02:36:41 +01:00
}
public function testCompleteExistingDefinition ()
{
$container = new ContainerBuilder ();
$container -> register ( 'b' , __NAMESPACE__ . '\B' );
2017-04-04 18:35:51 +01:00
$container -> register ( DInterface :: class , F :: class );
2015-08-24 02:36:41 +01:00
$hDefinition = $container -> register ( 'h' , __NAMESPACE__ . '\H' ) -> addArgument ( new Reference ( 'b' ));
$hDefinition -> setAutowired ( true );
2017-04-04 18:35:51 +01:00
( new ResolveClassPass ()) -> process ( $container );
( new AutowirePass ()) -> process ( $container );
2015-08-24 02:36:41 +01:00
$this -> assertCount ( 2 , $container -> getDefinition ( 'h' ) -> getArguments ());
$this -> assertEquals ( 'b' , ( string ) $container -> getDefinition ( 'h' ) -> getArgument ( 0 ));
2017-04-04 18:35:51 +01:00
$this -> assertEquals ( DInterface :: class , ( string ) $container -> getDefinition ( 'h' ) -> getArgument ( 1 ));
2015-08-24 02:36:41 +01:00
}
public function testCompleteExistingDefinitionWithNotDefinedArguments ()
{
$container = new ContainerBuilder ();
2017-04-04 18:35:51 +01:00
$container -> register ( B :: class );
$container -> register ( DInterface :: class , F :: class );
2015-08-24 02:36:41 +01:00
$hDefinition = $container -> register ( 'h' , __NAMESPACE__ . '\H' ) -> addArgument ( '' ) -> addArgument ( '' );
$hDefinition -> setAutowired ( true );
2017-04-04 18:35:51 +01:00
( new ResolveClassPass ()) -> process ( $container );
( new AutowirePass ()) -> process ( $container );
2015-08-24 02:36:41 +01:00
$this -> assertCount ( 2 , $container -> getDefinition ( 'h' ) -> getArguments ());
2017-04-04 18:35:51 +01:00
$this -> assertEquals ( B :: class , ( string ) $container -> getDefinition ( 'h' ) -> getArgument ( 0 ));
$this -> assertEquals ( DInterface :: class , ( string ) $container -> getDefinition ( 'h' ) -> getArgument ( 1 ));
2015-08-24 02:36:41 +01:00
}
2017-09-22 18:54:05 +01:00
/**
* @ group legacy
*/
2017-05-08 01:40:35 +01:00
public function testExceptionsAreStored ()
{
$container = new ContainerBuilder ();
$container -> register ( 'c1' , __NAMESPACE__ . '\CollisionA' );
$container -> register ( 'c2' , __NAMESPACE__ . '\CollisionB' );
$container -> register ( 'c3' , __NAMESPACE__ . '\CollisionB' );
$aDefinition = $container -> register ( 'a' , __NAMESPACE__ . '\CannotBeAutowired' );
$aDefinition -> setAutowired ( true );
$pass = new AutowirePass ( false );
$pass -> process ( $container );
$this -> assertCount ( 1 , $pass -> getAutowiringExceptions ());
}
2015-08-24 02:36:41 +01:00
/**
2017-05-31 14:45:25 +01:00
* @ expectedException \Symfony\Component\DependencyInjection\Exception\AutowiringFailedException
2017-09-23 23:04:06 +01:00
* @ expectedExceptionMessage Invalid service " private_service " : constructor of class " Symfony\Component\DependencyInjection\Tests\Compiler\PrivateConstructor " must be public.
2017-05-31 14:45:25 +01:00
*/
public function testPrivateConstructorThrowsAutowireException ()
{
$container = new ContainerBuilder ();
$container -> autowire ( 'private_service' , __NAMESPACE__ . '\PrivateConstructor' );
$pass = new AutowirePass ( true );
$pass -> process ( $container );
}
/**
* @ expectedException \Symfony\Component\DependencyInjection\Exception\AutowiringFailedException
2017-04-07 07:54:45 +01:00
* @ expectedExceptionMessage Cannot autowire service " a " : argument " $collision " of method " Symfony \ Component \ DependencyInjection \T ests \ Compiler \ CannotBeAutowired::__construct() " references interface " Symfony \ Component \ DependencyInjection \T ests \ Compiler \ CollisionInterface " but no such service exists . You should maybe alias this interface to one of these existing services : " c1 " , " c2 " , " c3 " .
2015-08-24 02:36:41 +01:00
*/
public function testTypeCollision ()
{
$container = new ContainerBuilder ();
$container -> register ( 'c1' , __NAMESPACE__ . '\CollisionA' );
$container -> register ( 'c2' , __NAMESPACE__ . '\CollisionB' );
2016-03-06 22:03:14 +00:00
$container -> register ( 'c3' , __NAMESPACE__ . '\CollisionB' );
2015-08-24 02:36:41 +01:00
$aDefinition = $container -> register ( 'a' , __NAMESPACE__ . '\CannotBeAutowired' );
$aDefinition -> setAutowired ( true );
$pass = new AutowirePass ();
$pass -> process ( $container );
}
2015-11-23 22:18:49 +00:00
/**
2017-05-31 14:45:25 +01:00
* @ expectedException \Symfony\Component\DependencyInjection\Exception\AutowiringFailedException
2017-04-07 07:54:45 +01:00
* @ expectedExceptionMessage Cannot autowire service " a " : argument " $k " of method " Symfony \ Component \ DependencyInjection \T ests \ Compiler \N otGuessableArgument::__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 " .
2015-11-23 22:18:49 +00:00
*/
public function testTypeNotGuessable ()
{
$container = new ContainerBuilder ();
$container -> register ( 'a1' , __NAMESPACE__ . '\Foo' );
$container -> register ( 'a2' , __NAMESPACE__ . '\Foo' );
$aDefinition = $container -> register ( 'a' , __NAMESPACE__ . '\NotGuessableArgument' );
$aDefinition -> setAutowired ( true );
$pass = new AutowirePass ();
$pass -> process ( $container );
}
/**
2017-05-31 14:45:25 +01:00
* @ expectedException \Symfony\Component\DependencyInjection\Exception\AutowiringFailedException
2017-04-07 07:54:45 +01:00
* @ expectedExceptionMessage Cannot autowire service " a " : argument " $k " of method " Symfony \ Component \ DependencyInjection \T ests \ Compiler \N otGuessableArgumentForSubclass::__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 " .
2015-11-23 22:18:49 +00:00
*/
public function testTypeNotGuessableWithSubclass ()
{
$container = new ContainerBuilder ();
$container -> register ( 'a1' , __NAMESPACE__ . '\B' );
$container -> register ( 'a2' , __NAMESPACE__ . '\B' );
$aDefinition = $container -> register ( 'a' , __NAMESPACE__ . '\NotGuessableArgumentForSubclass' );
$aDefinition -> setAutowired ( true );
$pass = new AutowirePass ();
$pass -> process ( $container );
}
2016-02-22 00:27:26 +00:00
/**
2017-05-31 14:45:25 +01:00
* @ expectedException \Symfony\Component\DependencyInjection\Exception\AutowiringFailedException
2017-04-04 18:35:51 +01:00
* @ expectedExceptionMessage Cannot autowire service " a " : argument " $collision " of method " Symfony \ Component \ DependencyInjection \T ests \ Compiler \ CannotBeAutowired::__construct() " references interface " Symfony \ Component \ DependencyInjection \T ests \ Compiler \ CollisionInterface " but no such service exists .
2016-02-22 00:27:26 +00:00
*/
public function testTypeNotGuessableNoServicesFound ()
{
$container = new ContainerBuilder ();
$aDefinition = $container -> register ( 'a' , __NAMESPACE__ . '\CannotBeAutowired' );
$aDefinition -> setAutowired ( true );
$pass = new AutowirePass ();
$pass -> process ( $container );
}
2015-11-23 22:18:49 +00:00
public function testTypeNotGuessableWithTypeSet ()
{
$container = new ContainerBuilder ();
$container -> register ( 'a1' , __NAMESPACE__ . '\Foo' );
2017-02-19 11:32:55 +00:00
$container -> register ( 'a2' , __NAMESPACE__ . '\Foo' );
2017-02-01 11:51:46 +00:00
$container -> register ( Foo :: class , Foo :: class );
2015-11-23 22:18:49 +00:00
$aDefinition = $container -> register ( 'a' , __NAMESPACE__ . '\NotGuessableArgument' );
$aDefinition -> setAutowired ( true );
$pass = new AutowirePass ();
$pass -> process ( $container );
$this -> assertCount ( 1 , $container -> getDefinition ( 'a' ) -> getArguments ());
2017-02-01 11:51:46 +00:00
$this -> assertEquals ( Foo :: class , ( string ) $container -> getDefinition ( 'a' ) -> getArgument ( 0 ));
2015-11-23 22:18:49 +00:00
}
2015-08-24 02:36:41 +01:00
public function testWithTypeSet ()
{
$container = new ContainerBuilder ();
$container -> register ( 'c1' , __NAMESPACE__ . '\CollisionA' );
2017-02-01 11:51:46 +00:00
$container -> register ( 'c2' , __NAMESPACE__ . '\CollisionB' );
$container -> setAlias ( CollisionInterface :: class , 'c2' );
2015-08-24 02:36:41 +01:00
$aDefinition = $container -> register ( 'a' , __NAMESPACE__ . '\CannotBeAutowired' );
$aDefinition -> setAutowired ( true );
$pass = new AutowirePass ();
$pass -> process ( $container );
$this -> assertCount ( 1 , $container -> getDefinition ( 'a' ) -> getArguments ());
2017-02-01 11:51:46 +00:00
$this -> assertEquals ( CollisionInterface :: class , ( string ) $container -> getDefinition ( 'a' ) -> getArgument ( 0 ));
2015-08-24 02:36:41 +01:00
}
2017-07-29 14:29:10 +01:00
/**
* @ group legacy
2017-12-31 06:25:36 +00:00
* @ expectedDeprecation Relying on service auto - registration for type " Symfony \ Component \ DependencyInjection \T ests \ Compiler \ Lille " is deprecated since Symfony 3.4 and won ' t be supported in 4.0 . Create a service named " Symfony \ Component \ DependencyInjection \T ests \ Compiler \ Lille " instead .
* @ expectedDeprecation Relying on service auto - registration for type " Symfony \ Component \ DependencyInjection \T ests \ Compiler \ Dunglas " is deprecated since Symfony 3.4 and won ' t be supported in 4.0 . Create a service named " Symfony \ Component \ DependencyInjection \T ests \ Compiler \ Dunglas " instead .
2017-07-29 14:29:10 +01:00
*/
2015-08-24 02:36:41 +01:00
public function testCreateDefinition ()
{
$container = new ContainerBuilder ();
$coopTilleulsDefinition = $container -> register ( 'coop_tilleuls' , __NAMESPACE__ . '\LesTilleuls' );
$coopTilleulsDefinition -> setAutowired ( true );
$pass = new AutowirePass ();
$pass -> process ( $container );
2017-04-06 15:56:22 +01:00
$this -> assertCount ( 2 , $container -> getDefinition ( 'coop_tilleuls' ) -> getArguments ());
2017-01-10 07:04:52 +00:00
$this -> assertEquals ( 'autowired.Symfony\Component\DependencyInjection\Tests\Compiler\Dunglas' , $container -> getDefinition ( 'coop_tilleuls' ) -> getArgument ( 0 ));
2017-04-07 07:15:11 +01:00
$this -> assertEquals ( 'autowired.Symfony\Component\DependencyInjection\Tests\Compiler\Dunglas' , $container -> getDefinition ( 'coop_tilleuls' ) -> getArgument ( 1 ));
2015-08-24 02:36:41 +01:00
2017-01-10 13:59:43 +00:00
$dunglasDefinition = $container -> getDefinition ( 'autowired.Symfony\Component\DependencyInjection\Tests\Compiler\Dunglas' );
2015-08-24 02:36:41 +01:00
$this -> assertEquals ( __NAMESPACE__ . '\Dunglas' , $dunglasDefinition -> getClass ());
$this -> assertFalse ( $dunglasDefinition -> isPublic ());
$this -> assertCount ( 1 , $dunglasDefinition -> getArguments ());
2017-01-10 07:04:52 +00:00
$this -> assertEquals ( 'autowired.Symfony\Component\DependencyInjection\Tests\Compiler\Lille' , $dunglasDefinition -> getArgument ( 0 ));
2015-08-24 02:36:41 +01:00
2017-01-10 13:59:43 +00:00
$lilleDefinition = $container -> getDefinition ( 'autowired.Symfony\Component\DependencyInjection\Tests\Compiler\Lille' );
2015-08-24 02:36:41 +01:00
$this -> assertEquals ( __NAMESPACE__ . '\Lille' , $lilleDefinition -> getClass ());
}
public function testResolveParameter ()
{
$container = new ContainerBuilder ();
2017-04-04 18:35:51 +01:00
$container -> setParameter ( 'class_name' , Bar :: class );
$container -> register ( Foo :: class );
$barDefinition = $container -> register ( 'bar' , '%class_name%' );
2015-08-24 02:36:41 +01:00
$barDefinition -> setAutowired ( true );
2017-04-04 18:35:51 +01:00
( new ResolveClassPass ()) -> process ( $container );
( new AutowirePass ()) -> process ( $container );
2015-08-24 02:36:41 +01:00
2017-04-04 18:35:51 +01:00
$this -> assertEquals ( Foo :: class , $container -> getDefinition ( 'bar' ) -> getArgument ( 0 ));
2015-08-24 02:36:41 +01:00
}
public function testOptionalParameter ()
{
$container = new ContainerBuilder ();
2017-04-04 18:35:51 +01:00
$container -> register ( A :: class );
$container -> register ( Foo :: class );
2015-08-24 02:36:41 +01:00
$optDefinition = $container -> register ( 'opt' , __NAMESPACE__ . '\OptionalParameter' );
$optDefinition -> setAutowired ( true );
2017-04-04 18:35:51 +01:00
( new ResolveClassPass ()) -> process ( $container );
( new AutowirePass ()) -> process ( $container );
2015-08-24 02:36:41 +01:00
$definition = $container -> getDefinition ( 'opt' );
$this -> assertNull ( $definition -> getArgument ( 0 ));
2017-04-04 18:35:51 +01:00
$this -> assertEquals ( A :: class , $definition -> getArgument ( 1 ));
$this -> assertEquals ( Foo :: class , $definition -> getArgument ( 2 ));
2015-08-24 02:36:41 +01:00
}
2015-11-03 19:42:49 +00:00
public function testDontTriggerAutowiring ()
2015-08-24 02:36:41 +01:00
{
$container = new ContainerBuilder ();
2017-04-04 18:35:51 +01:00
$container -> register ( Foo :: class );
2015-08-24 02:36:41 +01:00
$container -> register ( 'bar' , __NAMESPACE__ . '\Bar' );
2017-04-04 18:35:51 +01:00
( new ResolveClassPass ()) -> process ( $container );
( new AutowirePass ()) -> process ( $container );
2015-08-24 02:36:41 +01:00
$this -> assertCount ( 0 , $container -> getDefinition ( 'bar' ) -> getArguments ());
}
2015-11-04 18:04:11 +00:00
/**
2017-05-31 14:45:25 +01:00
* @ expectedException \Symfony\Component\DependencyInjection\Exception\AutowiringFailedException
2017-10-18 02:54:44 +01:00
* @ expectedExceptionMessage Cannot autowire service " a " : argument " $r " of method " Symfony \ Component \ DependencyInjection \T ests \ Compiler \ BadTypeHintedArgument::__construct() " has type " Symfony \ Component \ DependencyInjection \T ests \ Compiler \N otARealClass " but this class was not found .
2015-11-04 18:04:11 +00:00
*/
public function testClassNotFoundThrowsException ()
{
$container = new ContainerBuilder ();
$aDefinition = $container -> register ( 'a' , __NAMESPACE__ . '\BadTypeHintedArgument' );
$aDefinition -> setAutowired ( true );
2017-07-29 14:29:10 +01:00
$container -> register ( Dunglas :: class , Dunglas :: class );
2015-11-04 18:04:11 +00:00
$pass = new AutowirePass ();
$pass -> process ( $container );
}
2015-11-04 00:40:26 +00:00
2016-04-20 13:06:08 +01:00
/**
2017-05-31 14:45:25 +01:00
* @ expectedException \Symfony\Component\DependencyInjection\Exception\AutowiringFailedException
2017-10-18 02:54:44 +01:00
* @ expectedExceptionMessage Cannot autowire service " a " : argument " $r " of method " Symfony \ Component \ DependencyInjection \T ests \ Compiler \ BadParentTypeHintedArgument::__construct() " has type " Symfony \ Component \ DependencyInjection \T ests \ Compiler \ OptionalServiceClass " but this class is missing a parent class ( Class Symfony\Bug\NotExistClass not found ) .
2016-04-20 13:06:08 +01:00
*/
public function testParentClassNotFoundThrowsException ()
{
$container = new ContainerBuilder ();
$aDefinition = $container -> register ( 'a' , __NAMESPACE__ . '\BadParentTypeHintedArgument' );
$aDefinition -> setAutowired ( true );
2017-07-29 14:29:10 +01:00
$container -> register ( Dunglas :: class , Dunglas :: class );
2016-04-20 13:06:08 +01:00
$pass = new AutowirePass ();
$pass -> process ( $container );
}
2017-04-04 18:35:51 +01:00
/**
2017-04-11 22:05:55 +01:00
* @ group legacy
* @ expectedDeprecation Autowiring services based on the types they implement is deprecated since Symfony 3.3 and won ' t be supported in version 4.0 . You should rename ( or alias ) the " foo " service to " Symfony \ Component \ DependencyInjection \T ests \ Compiler \ Foo " instead .
2017-05-31 14:45:25 +01:00
* @ expectedExceptionInSymfony4 \Symfony\Component\DependencyInjection\Exception\AutowiringFailedException
2017-04-11 22:05:55 +01:00
* @ expectedExceptionMessageInSymfony4 Cannot autowire service " bar " : argument " $foo " of method " Symfony \ Component \ DependencyInjection \T ests \ 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.
2017-04-04 18:35:51 +01:00
*/
2015-11-04 00:40:26 +00:00
public function testDontUseAbstractServices ()
{
$container = new ContainerBuilder ();
2017-04-04 18:35:51 +01:00
$container -> register ( Foo :: class ) -> setAbstract ( true );
2015-11-04 00:40:26 +00:00
$container -> register ( 'foo' , __NAMESPACE__ . '\Foo' );
$container -> register ( 'bar' , __NAMESPACE__ . '\Bar' ) -> setAutowired ( true );
2017-04-04 18:35:51 +01:00
( new ResolveClassPass ()) -> process ( $container );
( new AutowirePass ()) -> process ( $container );
2015-11-04 00:40:26 +00:00
}
2016-02-21 23:51:49 +00:00
public function testSomeSpecificArgumentsAreSet ()
{
$container = new ContainerBuilder ();
2017-04-04 18:35:51 +01:00
$container -> register ( 'foo' , Foo :: class );
$container -> register ( A :: class );
$container -> register ( Dunglas :: class );
2016-02-21 23:51:49 +00:00
$container -> register ( 'multiple' , __NAMESPACE__ . '\MultipleArguments' )
-> setAutowired ( true )
// set the 2nd (index 1) argument only: autowire the first and third
// args are: A, Foo, Dunglas
2019-01-16 09:39:14 +00:00
-> setArguments ([
2016-02-21 23:51:49 +00:00
1 => new Reference ( 'foo' ),
2019-01-16 09:39:14 +00:00
3 => [ 'bar' ],
]);
2016-02-21 23:51:49 +00:00
2017-04-04 18:35:51 +01:00
( new ResolveClassPass ()) -> process ( $container );
( new AutowirePass ()) -> process ( $container );
2016-02-21 23:51:49 +00:00
$definition = $container -> getDefinition ( 'multiple' );
$this -> assertEquals (
2019-01-16 09:39:14 +00:00
[
2017-04-06 09:48:39 +01:00
new TypedReference ( A :: class , A :: class , MultipleArguments :: class ),
2016-02-21 23:51:49 +00:00
new Reference ( 'foo' ),
2017-04-06 09:48:39 +01:00
new TypedReference ( Dunglas :: class , Dunglas :: class , MultipleArguments :: class ),
2019-01-16 09:39:14 +00:00
[ 'bar' ],
],
2016-02-21 23:51:49 +00:00
$definition -> getArguments ()
);
}
2016-02-22 01:17:09 +00:00
/**
2017-05-31 14:45:25 +01:00
* @ expectedException \Symfony\Component\DependencyInjection\Exception\AutowiringFailedException
2018-04-07 14:42:06 +01:00
* @ expectedExceptionMessage Cannot autowire service " arg_no_type_hint " : argument " $bar " of method " Symfony \ Component \ DependencyInjection \T ests \ Compiler \ MultipleArguments::__construct() " is type - hinted " array " , you should configure its value explicitly .
2016-02-22 01:17:09 +00:00
*/
public function testScalarArgsCannotBeAutowired ()
{
$container = new ContainerBuilder ();
2018-04-07 14:42:06 +01:00
$container -> register ( A :: class );
$container -> register ( Dunglas :: class );
$container -> register ( 'arg_no_type_hint' , __NAMESPACE__ . '\MultipleArguments' )
2019-01-16 09:39:14 +00:00
-> setArguments ([ 1 => 'foo' ])
2018-04-07 14:42:06 +01:00
-> setAutowired ( true );
( new ResolveClassPass ()) -> process ( $container );
( new AutowirePass ()) -> process ( $container );
}
/**
* @ expectedException \Symfony\Component\DependencyInjection\Exception\AutowiringFailedException
* @ expectedExceptionMessage Cannot autowire service " arg_no_type_hint " : argument " $foo " of method " Symfony \ Component \ DependencyInjection \T ests \ Compiler \ MultipleArguments::__construct() " has no type - hint , you should configure its value explicitly .
*/
public function testNoTypeArgsCannotBeAutowired ()
{
$container = new ContainerBuilder ();
2017-04-04 18:35:51 +01:00
$container -> register ( A :: class );
$container -> register ( Dunglas :: class );
2016-02-22 01:17:09 +00:00
$container -> register ( 'arg_no_type_hint' , __NAMESPACE__ . '\MultipleArguments' )
-> setAutowired ( true );
2017-04-04 18:35:51 +01:00
( new ResolveClassPass ()) -> process ( $container );
( new AutowirePass ()) -> process ( $container );
2016-02-22 01:17:09 +00:00
}
2017-04-03 15:43:13 +01:00
public function testOptionalScalarNotReallyOptionalUsesDefaultValue ()
2016-02-22 01:17:09 +00:00
{
$container = new ContainerBuilder ();
2017-04-04 18:35:51 +01:00
$container -> register ( A :: class );
$container -> register ( Lille :: class );
2017-04-03 15:43:13 +01:00
$definition = $container -> register ( 'not_really_optional_scalar' , __NAMESPACE__ . '\MultipleArgumentsOptionalScalarNotReallyOptional' )
2016-02-22 01:17:09 +00:00
-> setAutowired ( true );
2017-04-04 18:35:51 +01:00
( new ResolveClassPass ()) -> process ( $container );
( new AutowirePass ()) -> process ( $container );
2017-04-03 15:43:13 +01:00
$this -> assertSame ( 'default_val' , $definition -> getArgument ( 1 ));
2016-02-22 01:17:09 +00:00
}
public function testOptionalScalarArgsDontMessUpOrder ()
{
$container = new ContainerBuilder ();
2017-04-04 18:35:51 +01:00
$container -> register ( A :: class );
$container -> register ( Lille :: class );
2016-02-22 01:17:09 +00:00
$container -> register ( 'with_optional_scalar' , __NAMESPACE__ . '\MultipleArgumentsOptionalScalar' )
-> setAutowired ( true );
2017-04-04 18:35:51 +01:00
( new ResolveClassPass ()) -> process ( $container );
( new AutowirePass ()) -> process ( $container );
2016-02-22 01:17:09 +00:00
$definition = $container -> getDefinition ( 'with_optional_scalar' );
$this -> assertEquals (
2019-01-16 09:39:14 +00:00
[
2017-04-06 09:48:39 +01:00
new TypedReference ( A :: class , A :: class , MultipleArgumentsOptionalScalar :: class ),
2016-02-22 01:17:09 +00:00
// use the default value
'default_val' ,
2017-04-06 09:48:39 +01:00
new TypedReference ( Lille :: class , Lille :: class ),
2019-01-16 09:39:14 +00:00
],
2016-02-22 01:17:09 +00:00
$definition -> getArguments ()
);
}
public function testOptionalScalarArgsNotPassedIfLast ()
{
$container = new ContainerBuilder ();
2017-04-04 18:35:51 +01:00
$container -> register ( A :: class );
$container -> register ( Lille :: class );
2016-02-22 01:17:09 +00:00
$container -> register ( 'with_optional_scalar_last' , __NAMESPACE__ . '\MultipleArgumentsOptionalScalarLast' )
-> setAutowired ( true );
2017-04-04 18:35:51 +01:00
( new ResolveClassPass ()) -> process ( $container );
( new AutowirePass ()) -> process ( $container );
2016-02-22 01:17:09 +00:00
$definition = $container -> getDefinition ( 'with_optional_scalar_last' );
$this -> assertEquals (
2019-01-16 09:39:14 +00:00
[
2017-04-06 09:48:39 +01:00
new TypedReference ( A :: class , A :: class , MultipleArgumentsOptionalScalarLast :: class ),
new TypedReference ( Lille :: class , Lille :: class , MultipleArgumentsOptionalScalarLast :: class ),
2019-01-16 09:39:14 +00:00
],
2016-02-22 01:17:09 +00:00
$definition -> getArguments ()
);
}
2016-03-12 20:10:13 +00:00
2017-07-21 00:10:01 +01:00
public function testOptionalArgsNoRequiredForCoreClasses ()
{
$container = new ContainerBuilder ();
2017-07-23 10:15:20 +01:00
$container -> register ( 'foo' , \SplFileObject :: class )
-> addArgument ( 'foo.txt' )
2017-07-21 00:10:01 +01:00
-> setAutowired ( true );
( new AutowirePass ()) -> process ( $container );
2017-07-23 10:15:20 +01:00
$definition = $container -> getDefinition ( 'foo' );
2017-07-21 00:10:01 +01:00
$this -> assertEquals (
2019-01-16 09:39:14 +00:00
[ 'foo.txt' ],
2017-07-21 00:10:01 +01:00
$definition -> getArguments ()
);
}
2016-10-05 21:46:29 +01:00
public function testSetterInjection ()
{
$container = new ContainerBuilder ();
2017-04-04 18:35:51 +01:00
$container -> register ( Foo :: class );
$container -> register ( A :: class );
$container -> register ( CollisionA :: class );
$container -> register ( CollisionB :: class );
2016-10-05 21:46:29 +01:00
// manually configure *one* call, to override autowiring
$container
-> register ( 'setter_injection' , SetterInjection :: class )
2017-02-25 16:12:16 +00:00
-> setAutowired ( true )
2019-01-16 09:39:14 +00:00
-> addMethodCall ( 'setWithCallsConfigured' , [ 'manual_arg1' , 'manual_arg2' ])
2016-10-05 21:46:29 +01:00
;
2017-04-04 18:35:51 +01:00
( new ResolveClassPass ()) -> process ( $container );
2017-09-23 23:04:06 +01:00
( new AutowireRequiredMethodsPass ()) -> process ( $container );
2017-04-04 18:35:51 +01:00
( new AutowirePass ()) -> process ( $container );
2016-10-05 21:46:29 +01:00
$methodCalls = $container -> getDefinition ( 'setter_injection' ) -> getMethodCalls ();
$this -> assertEquals (
2019-01-16 09:39:14 +00:00
[ 'setWithCallsConfigured' , 'setFoo' , 'setDependencies' , 'setChildMethodWithoutDocBlock' ],
2017-02-25 16:12:16 +00:00
array_column ( $methodCalls , 0 )
2016-10-05 21:46:29 +01:00
);
// test setWithCallsConfigured args
$this -> assertEquals (
2019-01-16 09:39:14 +00:00
[ 'manual_arg1' , 'manual_arg2' ],
2016-10-05 21:46:29 +01:00
$methodCalls [ 0 ][ 1 ]
);
// test setFoo args
$this -> assertEquals (
2019-01-16 09:39:14 +00:00
[ new TypedReference ( Foo :: class , Foo :: class , SetterInjection :: class )],
2016-10-05 21:46:29 +01:00
$methodCalls [ 1 ][ 1 ]
);
}
public function testExplicitMethodInjection ()
{
$container = new ContainerBuilder ();
2017-04-04 18:35:51 +01:00
$container -> register ( Foo :: class );
$container -> register ( A :: class );
$container -> register ( CollisionA :: class );
$container -> register ( CollisionB :: class );
2016-10-05 21:46:29 +01:00
$container
-> register ( 'setter_injection' , SetterInjection :: class )
2017-02-25 16:12:16 +00:00
-> setAutowired ( true )
2019-01-16 09:39:14 +00:00
-> addMethodCall ( 'notASetter' , [])
2016-10-05 21:46:29 +01:00
;
2017-04-04 18:35:51 +01:00
( new ResolveClassPass ()) -> process ( $container );
2017-09-23 23:04:06 +01:00
( new AutowireRequiredMethodsPass ()) -> process ( $container );
2017-04-04 18:35:51 +01:00
( new AutowirePass ()) -> process ( $container );
2016-10-05 21:46:29 +01:00
$methodCalls = $container -> getDefinition ( 'setter_injection' ) -> getMethodCalls ();
$this -> assertEquals (
2019-01-16 09:39:14 +00:00
[ 'notASetter' , 'setFoo' , 'setDependencies' , 'setWithCallsConfigured' , 'setChildMethodWithoutDocBlock' ],
2017-02-25 16:12:16 +00:00
array_column ( $methodCalls , 0 )
);
$this -> assertEquals (
2019-01-16 09:39:14 +00:00
[ new TypedReference ( A :: class , A :: class , SetterInjection :: class )],
2017-02-25 16:12:16 +00:00
$methodCalls [ 0 ][ 1 ]
2016-10-05 21:46:29 +01:00
);
}
2017-07-29 14:29:10 +01:00
/**
* @ group legacy
2017-12-31 06:25:36 +00:00
* @ expectedDeprecation Relying on service auto - registration for type " Symfony \ Component \ DependencyInjection \T ests \ Compiler \ A " is deprecated since Symfony 3.4 and won ' t be supported in 4.0 . Create a service named " Symfony \ Component \ DependencyInjection \T ests \ Compiler \ A " instead .
2017-07-29 14:29:10 +01:00
*/
2017-03-05 22:31:39 +00:00
public function testTypedReference ()
2017-02-26 17:31:03 +00:00
{
$container = new ContainerBuilder ();
$container
-> register ( 'bar' , Bar :: class )
2019-01-16 09:39:14 +00:00
-> setProperty ( 'a' , [ new TypedReference ( A :: class , A :: class , Bar :: class )])
2017-02-26 17:31:03 +00:00
;
$pass = new AutowirePass ();
$pass -> process ( $container );
$this -> assertSame ( A :: class , $container -> getDefinition ( 'autowired.' . A :: class ) -> getClass ());
}
2016-03-12 20:10:13 +00:00
/**
* @ dataProvider getCreateResourceTests
2017-01-26 15:09:57 +00:00
* @ group legacy
2016-03-12 20:10:13 +00:00
*/
public function testCreateResourceForClass ( $className , $isEqual )
{
$startingResource = AutowirePass :: createResourceForClass (
new \ReflectionClass ( __NAMESPACE__ . '\ClassForResource' )
);
$newResource = AutowirePass :: createResourceForClass (
new \ReflectionClass ( __NAMESPACE__ . '\\' . $className )
);
// hack so the objects don't differ by the class name
$startingReflObject = new \ReflectionObject ( $startingResource );
$reflProp = $startingReflObject -> getProperty ( 'class' );
$reflProp -> setAccessible ( true );
$reflProp -> setValue ( $startingResource , __NAMESPACE__ . '\\' . $className );
if ( $isEqual ) {
$this -> assertEquals ( $startingResource , $newResource );
} else {
$this -> assertNotEquals ( $startingResource , $newResource );
}
}
public function getCreateResourceTests ()
{
2019-01-16 09:39:14 +00:00
return [
[ 'IdenticalClassResource' , true ],
[ 'ClassChangedConstructorArgs' , false ],
];
2016-03-12 20:10:13 +00:00
}
2016-04-25 12:21:08 +01:00
2016-03-31 13:26:29 +01:00
public function testIgnoreServiceWithClassNotExisting ()
{
$container = new ContainerBuilder ();
$container -> register ( 'class_not_exist' , __NAMESPACE__ . '\OptionalServiceClass' );
$barDefinition = $container -> register ( 'bar' , __NAMESPACE__ . '\Bar' );
$barDefinition -> setAutowired ( true );
2017-07-29 14:29:10 +01:00
$container -> register ( Foo :: class , Foo :: class );
2016-03-31 13:26:29 +01:00
$pass = new AutowirePass ();
$pass -> process ( $container );
$this -> assertTrue ( $container -> hasDefinition ( 'bar' ));
}
2016-10-05 21:46:29 +01:00
public function testSetterInjectionCollisionThrowsException ()
{
$container = new ContainerBuilder ();
$container -> register ( 'c1' , CollisionA :: class );
$container -> register ( 'c2' , CollisionB :: class );
$aDefinition = $container -> register ( 'setter_injection_collision' , SetterInjectionCollision :: class );
2017-02-25 16:12:16 +00:00
$aDefinition -> setAutowired ( true );
2016-10-05 21:46:29 +01:00
2017-09-23 23:04:06 +01:00
( new AutowireRequiredMethodsPass ()) -> process ( $container );
2017-12-19 11:02:38 +00:00
$pass = new AutowirePass ();
2018-03-19 09:44:01 +00:00
try {
$pass -> process ( $container );
} catch ( AutowiringFailedException $e ) {
}
$this -> assertNotNull ( $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".' , $e -> getMessage ());
2017-12-19 11:02:38 +00:00
}
/**
* @ expectedException \Symfony\Component\DependencyInjection\Exception\AutowiringFailedException
* @ expectedExceptionMessage Cannot autowire service " my_service " : argument " $i " of method " Symfony \ Component \ DependencyInjection \T ests \ Compiler \ K::__construct() " references interface " Symfony \ Component \ DependencyInjection \T ests \ Compiler \ IInterface " but no such service exists . Did you create a class that implements this interface ?
*/
public function testInterfaceWithNoImplementationSuggestToWriteOne ()
{
$container = new ContainerBuilder ();
$aDefinition = $container -> register ( 'my_service' , K :: class );
$aDefinition -> setAutowired ( true );
( new AutowireRequiredMethodsPass ()) -> process ( $container );
2017-09-23 23:04:06 +01:00
2016-10-05 21:46:29 +01:00
$pass = new AutowirePass ();
2017-04-05 22:43:54 +01:00
$pass -> process ( $container );
}
2017-04-04 18:35:51 +01:00
/**
2017-04-11 22:05:55 +01:00
* @ group legacy
* @ expectedDeprecation Autowiring services based on the types they implement is deprecated since Symfony 3.3 and won ' t be supported in version 4.0 . You should rename ( or alias ) the " foo " service to " Symfony \ Component \ DependencyInjection \T ests \ Compiler \ Foo " instead .
2017-05-31 14:45:25 +01:00
* @ expectedExceptionInSymfony4 \Symfony\Component\DependencyInjection\Exception\AutowiringFailedException
2017-04-11 22:05:55 +01:00
* @ expectedExceptionMessageInSymfony4 Cannot autowire service " bar " : argument " $foo " of method " Symfony \ Component \ DependencyInjection \T ests \ 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.
2017-04-04 18:35:51 +01:00
*/
2017-04-04 20:38:24 +01:00
public function testProcessDoesNotTriggerDeprecations ()
{
$container = new ContainerBuilder ();
$container -> register ( 'deprecated' , 'Symfony\Component\DependencyInjection\Tests\Fixtures\DeprecatedClass' ) -> setDeprecated ( true );
$container -> register ( 'foo' , __NAMESPACE__ . '\Foo' );
$container -> register ( 'bar' , __NAMESPACE__ . '\Bar' ) -> setAutowired ( true );
$pass = new AutowirePass ();
2016-10-05 21:46:29 +01:00
$pass -> process ( $container );
2017-04-11 10:19:47 +01:00
$this -> assertTrue ( $container -> hasDefinition ( 'deprecated' ));
$this -> assertTrue ( $container -> hasDefinition ( 'foo' ));
$this -> assertTrue ( $container -> hasDefinition ( 'bar' ));
2016-10-05 21:46:29 +01:00
}
2017-01-25 12:02:51 +00:00
2017-01-25 12:10:29 +00:00
public function testEmptyStringIsKept ()
{
$container = new ContainerBuilder ();
2017-04-04 18:35:51 +01:00
$container -> register ( A :: class );
$container -> register ( Lille :: class );
2017-01-25 12:10:29 +00:00
$container -> register ( 'foo' , __NAMESPACE__ . '\MultipleArgumentsOptionalScalar' )
-> setAutowired ( true )
2019-01-16 09:39:14 +00:00
-> setArguments ([ '' , '' ]);
2017-01-25 12:02:51 +00:00
2017-04-04 18:35:51 +01:00
( new ResolveClassPass ()) -> process ( $container );
( new AutowirePass ()) -> process ( $container );
2017-01-25 12:02:51 +00:00
2019-01-16 09:39:14 +00:00
$this -> assertEquals ([ new TypedReference ( A :: class , A :: class , MultipleArgumentsOptionalScalar :: class ), '' , new TypedReference ( Lille :: class , Lille :: class )], $container -> getDefinition ( 'foo' ) -> getArguments ());
2017-01-25 12:02:51 +00:00
}
2017-02-18 11:21:50 +00:00
2017-04-04 08:47:41 +01:00
public function testWithFactory ()
2017-02-18 11:21:50 +00:00
{
$container = new ContainerBuilder ();
2017-04-04 18:35:51 +01:00
$container -> register ( Foo :: class );
2017-04-04 14:48:08 +01:00
$definition = $container -> register ( 'a' , A :: class )
2019-01-16 09:39:14 +00:00
-> setFactory ([ A :: class , 'create' ])
2017-02-18 11:21:50 +00:00
-> setAutowired ( true );
2017-04-04 18:35:51 +01:00
( new ResolveClassPass ()) -> process ( $container );
( new AutowirePass ()) -> process ( $container );
2017-04-04 14:48:08 +01:00
2019-01-16 09:39:14 +00:00
$this -> assertEquals ([ new TypedReference ( Foo :: class , Foo :: class , A :: class )], $definition -> getArguments ());
2017-02-18 11:21:50 +00:00
}
2017-03-17 09:21:51 +00:00
/**
* @ dataProvider provideNotWireableCalls
2017-05-31 14:45:25 +01:00
* @ expectedException \Symfony\Component\DependencyInjection\Exception\AutowiringFailedException
2017-03-17 09:21:51 +00:00
*/
public function testNotWireableCalls ( $method , $expectedMsg )
{
$container = new ContainerBuilder ();
2017-04-03 15:43:13 +01:00
$foo = $container -> register ( 'foo' , NotWireable :: class ) -> setAutowired ( true )
2019-01-16 09:39:14 +00:00
-> addMethodCall ( 'setBar' , [])
-> addMethodCall ( 'setOptionalNotAutowireable' , [])
-> addMethodCall ( 'setOptionalNoTypeHint' , [])
-> addMethodCall ( 'setOptionalArgNoAutowireable' , [])
2017-04-03 15:43:13 +01:00
;
2017-03-17 09:21:51 +00:00
if ( $method ) {
2019-01-16 09:39:14 +00:00
$foo -> addMethodCall ( $method , []);
2017-03-17 09:21:51 +00:00
}
if ( method_exists ( $this , 'expectException' )) {
$this -> expectException ( RuntimeException :: class );
$this -> expectExceptionMessage ( $expectedMsg );
} else {
$this -> setExpectedException ( RuntimeException :: class , $expectedMsg );
}
2017-04-04 18:35:51 +01:00
( new ResolveClassPass ()) -> process ( $container );
2017-09-23 23:04:06 +01:00
( new AutowireRequiredMethodsPass ()) -> process ( $container );
2017-04-04 18:35:51 +01:00
( new AutowirePass ()) -> process ( $container );
2017-03-17 09:21:51 +00:00
}
public function provideNotWireableCalls ()
{
2019-01-16 09:39:14 +00:00
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. It cannot be auto-registered because it is from a different root namespace.' ],
[ null , 'Invalid service "foo": method "Symfony\Component\DependencyInjection\Tests\Compiler\NotWireable::setProtectedMethod()" must be public.' ],
];
2017-03-17 09:21:51 +00:00
}
2017-03-21 15:17:00 +00:00
2017-03-23 22:53:25 +00:00
/**
2017-04-11 22:05:55 +01:00
* @ group legacy
2017-05-05 12:31:04 +01:00
* @ expectedDeprecation Autowiring services based on the types they implement is deprecated since Symfony 3.3 and won ' t be supported in version 4.0 . Try changing the type - hint for argument " $i " of method " Symfony \ Component \ DependencyInjection \T ests \ Compiler \ J::__construct() " to " Symfony \ Component \ DependencyInjection \T ests \ Compiler \ IInterface " instead .
2017-05-31 14:45:25 +01:00
* @ expectedExceptionInSymfony4 \Symfony\Component\DependencyInjection\Exception\AutowiringFailedException
2017-05-05 12:31:04 +01:00
* @ expectedExceptionMessageInSymfony4 Cannot autowire service " j " : argument " $i " of method " Symfony \ Component \ DependencyInjection \T ests \ 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.
2017-03-19 11:22:02 +00:00
*/
public function testByIdAlternative ()
{
$container = new ContainerBuilder ();
$container -> setAlias ( IInterface :: class , 'i' );
$container -> register ( 'i' , I :: class );
$container -> register ( 'j' , J :: class )
2017-04-04 18:35:51 +01:00
-> setAutowired ( true );
2017-03-19 11:22:02 +00:00
$pass = new AutowirePass ();
$pass -> process ( $container );
}
2017-05-05 12:31:04 +01:00
2017-05-05 12:31:04 +01:00
/**
* @ group legacy
* @ expectedDeprecation Autowiring services based on the types they implement is deprecated since Symfony 3.3 and won ' t be supported in version 4.0 . Try changing the type - hint for " Symfony \ Component \ DependencyInjection \T ests \ Compiler \ A " in " Symfony \ Component \ DependencyInjection \T ests \ Compiler \ Bar " to " Symfony \ Component \ DependencyInjection \T ests \ Compiler \ AInterface " instead .
*/
public function testTypedReferenceDeprecationNotice ()
{
$container = new ContainerBuilder ();
$container -> register ( 'aClass' , A :: class );
$container -> setAlias ( AInterface :: class , 'aClass' );
$container
-> register ( 'bar' , Bar :: class )
2019-01-16 09:39:14 +00:00
-> setProperty ( 'a' , [ new TypedReference ( A :: class , A :: class , Bar :: class )])
2017-05-05 12:31:04 +01:00
;
$pass = new AutowirePass ();
$pass -> process ( $container );
}
2017-05-05 12:31:04 +01:00
/**
2017-05-31 14:45:25 +01:00
* @ expectedException \Symfony\Component\DependencyInjection\Exception\AutowiringFailedException
2017-05-05 12:31:04 +01:00
* @ expectedExceptionMessage Cannot autowire service " j " : argument " $i " of method " Symfony \ Component \ DependencyInjection \T ests \ 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.
*/
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 ();
$pass -> process ( $container );
}
/**
2017-05-31 14:45:25 +01:00
* @ expectedException \Symfony\Component\DependencyInjection\Exception\AutowiringFailedException
2017-05-05 12:31:04 +01:00
* @ expectedExceptionMessage Cannot autowire service " j " : argument " $i " of method " Symfony \ Component \ DependencyInjection \T ests \ 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 " .
*/
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 ();
$pass -> process ( $container );
}
2017-10-08 15:29:36 +01:00
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 );
2019-01-16 09:39:14 +00:00
$this -> assertSame ([], $container -> getDefinition ( 'autowired' ) -> getArguments ());
2017-10-08 15:29:36 +01:00
}
2015-08-24 02:36:41 +01:00
}