2010-03-18 07:48:03 +00:00
< ? php
/*
2010-04-25 16:06:54 +01:00
* This file is part of the Symfony package .
2011-01-15 13:29:43 +00:00
*
2011-03-06 11:40:06 +00:00
* ( c ) Fabien Potencier < fabien @ symfony . com >
2010-04-07 02:07:59 +01:00
*
2010-03-18 07:48:03 +00:00
* For the full copyright and license information , please view the LICENSE
* file that was distributed with this source code .
*/
2010-08-20 22:09:55 +01:00
namespace Symfony\Tests\Component\DependencyInjection ;
2010-03-18 07:48:03 +00:00
2011-02-13 09:33:53 +00:00
use Symfony\Component\DependencyInjection\Scope ;
2010-08-20 22:09:55 +01:00
use Symfony\Component\DependencyInjection\Container ;
use Symfony\Component\DependencyInjection\ContainerInterface ;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag ;
2010-03-18 07:48:03 +00:00
class ContainerTest extends \PHPUnit_Framework_TestCase
{
2010-06-27 17:28:29 +01:00
/**
2010-08-20 22:09:55 +01:00
* @ covers Symfony\Component\DependencyInjection\Container :: __construct
2010-06-27 17:28:29 +01:00
*/
2010-05-06 12:25:53 +01:00
public function testConstructor ()
{
$sc = new Container ();
2010-11-20 01:09:20 +00:00
$this -> assertSame ( $sc , $sc -> get ( 'service_container' ), '__construct() automatically registers itself as a service' );
2010-03-18 07:48:03 +00:00
2010-06-27 17:28:29 +01:00
$sc = new Container ( new ParameterBag ( array ( 'foo' => 'bar' )));
$this -> assertEquals ( array ( 'foo' => 'bar' ), $sc -> getParameterBag () -> all (), '__construct() takes an array of parameters as its first argument' );
2010-05-06 12:25:53 +01:00
}
2010-03-18 07:48:03 +00:00
2010-06-27 17:28:29 +01:00
/**
2011-01-16 07:12:36 +00:00
* @ covers Symfony\Component\DependencyInjection\Container :: compile
2010-06-27 17:28:29 +01:00
*/
2011-02-19 18:30:12 +00:00
public function testCompile ()
2010-05-06 12:25:53 +01:00
{
2010-06-27 17:28:29 +01:00
$sc = new Container ( new ParameterBag ( array ( 'foo' => 'bar' )));
2011-01-16 07:12:36 +00:00
$sc -> compile ();
$this -> assertInstanceOf ( 'Symfony\Component\DependencyInjection\ParameterBag\FrozenParameterBag' , $sc -> getParameterBag (), '->compile() changes the parameter bag to a FrozenParameterBag instance' );
$this -> assertEquals ( array ( 'foo' => 'bar' ), $sc -> getParameterBag () -> all (), '->compile() copies the current parameters to the new parameter bag' );
2010-06-27 17:28:29 +01:00
}
2010-03-18 07:48:03 +00:00
2010-06-27 17:28:29 +01:00
/**
2010-08-20 22:09:55 +01:00
* @ covers Symfony\Component\DependencyInjection\Container :: isFrozen
2010-06-27 17:28:29 +01:00
*/
public function testIsFrozen ()
{
$sc = new Container ( new ParameterBag ( array ( 'foo' => 'bar' )));
$this -> assertFalse ( $sc -> isFrozen (), '->isFrozen() returns false if the parameters are not frozen' );
2011-01-16 07:12:36 +00:00
$sc -> compile ();
2010-06-27 17:28:29 +01:00
$this -> assertTrue ( $sc -> isFrozen (), '->isFrozen() returns true if the parameters are frozen' );
}
2010-03-18 07:48:03 +00:00
2010-06-27 17:28:29 +01:00
/**
2010-08-20 22:09:55 +01:00
* @ covers Symfony\Component\DependencyInjection\Container :: getParameterBag
2010-06-27 17:28:29 +01:00
*/
public function testGetParameterBag ()
{
$sc = new Container ();
$this -> assertEquals ( array (), $sc -> getParameterBag () -> all (), '->getParameterBag() returns an empty array if no parameter has been defined' );
2010-03-18 07:48:03 +00:00
}
2010-06-27 17:28:29 +01:00
/**
2010-08-20 22:09:55 +01:00
* @ covers Symfony\Component\DependencyInjection\Container :: setParameter
* @ covers Symfony\Component\DependencyInjection\Container :: getParameter
2010-06-27 17:28:29 +01:00
*/
2010-05-06 12:25:53 +01:00
public function testGetSetParameter ()
2010-03-18 07:48:03 +00:00
{
2010-06-27 17:28:29 +01:00
$sc = new Container ( new ParameterBag ( array ( 'foo' => 'bar' )));
2010-05-06 12:25:53 +01:00
$sc -> setParameter ( 'bar' , 'foo' );
$this -> assertEquals ( 'foo' , $sc -> getParameter ( 'bar' ), '->setParameter() sets the value of a new parameter' );
$sc -> setParameter ( 'foo' , 'baz' );
$this -> assertEquals ( 'baz' , $sc -> getParameter ( 'foo' ), '->setParameter() overrides previously set parameter' );
$sc -> setParameter ( 'Foo' , 'baz1' );
$this -> assertEquals ( 'baz1' , $sc -> getParameter ( 'foo' ), '->setParameter() converts the key to lowercase' );
$this -> assertEquals ( 'baz1' , $sc -> getParameter ( 'FOO' ), '->getParameter() converts the key to lowercase' );
2010-05-07 15:09:11 +01:00
try {
2010-05-06 12:25:53 +01:00
$sc -> getParameter ( 'baba' );
$this -> fail ( '->getParameter() thrown an \InvalidArgumentException if the key does not exist' );
2010-05-07 15:09:11 +01:00
} catch ( \Exception $e ) {
2010-05-06 12:25:53 +01:00
$this -> assertInstanceOf ( '\InvalidArgumentException' , $e , '->getParameter() thrown an \InvalidArgumentException if the key does not exist' );
$this -> assertEquals ( 'The parameter "baba" must be defined.' , $e -> getMessage (), '->getParameter() thrown an \InvalidArgumentException if the key does not exist' );
}
2010-03-18 07:48:03 +00:00
}
2010-05-06 12:25:53 +01:00
2010-06-27 17:28:29 +01:00
/**
2010-08-20 22:09:55 +01:00
* @ covers Symfony\Component\DependencyInjection\Container :: getServiceIds
2010-06-27 17:28:29 +01:00
*/
public function testGetServiceIds ()
2010-03-18 07:48:03 +00:00
{
2010-06-27 17:28:29 +01:00
$sc = new Container ();
$sc -> set ( 'foo' , $obj = new \stdClass ());
$sc -> set ( 'bar' , $obj = new \stdClass ());
$this -> assertEquals ( array ( 'service_container' , 'foo' , 'bar' ), $sc -> getServiceIds (), '->getServiceIds() returns all defined service ids' );
2010-05-06 12:25:53 +01:00
2010-06-27 17:28:29 +01:00
$sc = new ProjectServiceContainer ();
2011-03-09 14:38:02 +00:00
$this -> assertEquals ( array ( 'scoped' , 'scoped_foo' , 'bar' , 'foo_bar' , 'foo.baz' , 'circular' , 'throw_exception' , 'service_container' ), $sc -> getServiceIds (), '->getServiceIds() returns defined service ids by getXXXService() methods' );
2010-03-18 07:48:03 +00:00
}
2010-06-27 17:28:29 +01:00
/**
2010-08-20 22:09:55 +01:00
* @ covers Symfony\Component\DependencyInjection\Container :: set
2010-06-27 17:28:29 +01:00
*/
public function testSet ()
2010-03-18 07:48:03 +00:00
{
2010-05-06 12:25:53 +01:00
$sc = new Container ();
2010-06-27 17:28:29 +01:00
$sc -> set ( 'foo' , $foo = new \stdClass ());
$this -> assertEquals ( $foo , $sc -> get ( 'foo' ), '->set() sets a service' );
}
2010-05-06 12:25:53 +01:00
2011-01-17 22:28:59 +00:00
/**
* @ expectedException \InvalidArgumentException
*/
public function testSetDoesNotAllowPrototypeScope ()
{
$c = new Container ();
$c -> set ( 'foo' , new \stdClass (), 'prototype' );
}
/**
* @ expectedException \RuntimeException
*/
public function testSetDoesNotAllowInactiveScope ()
{
$c = new Container ();
2011-02-13 09:33:53 +00:00
$c -> addScope ( new Scope ( 'foo' ));
2011-01-17 22:28:59 +00:00
$c -> set ( 'foo' , new \stdClass (), 'foo' );
}
public function testSetAlsoSetsScopedService ()
{
$c = new Container ();
2011-02-13 09:33:53 +00:00
$c -> addScope ( new Scope ( 'foo' ));
2011-01-17 22:28:59 +00:00
$c -> enterScope ( 'foo' );
$c -> set ( 'foo' , $foo = new \stdClass (), 'foo' );
$services = $this -> getField ( $c , 'scopedServices' );
$this -> assertTrue ( isset ( $services [ 'foo' ][ 'foo' ]));
$this -> assertSame ( $foo , $services [ 'foo' ][ 'foo' ]);
}
2010-06-27 17:28:29 +01:00
/**
2010-08-20 22:09:55 +01:00
* @ covers Symfony\Component\DependencyInjection\Container :: get
2010-06-27 17:28:29 +01:00
*/
public function testGet ()
{
2010-05-06 12:25:53 +01:00
$sc = new ProjectServiceContainer ();
2010-06-27 17:28:29 +01:00
$sc -> set ( 'foo' , $foo = new \stdClass ());
$this -> assertEquals ( $foo , $sc -> get ( 'foo' ), '->get() returns the service for the given id' );
$this -> assertEquals ( $sc -> __bar , $sc -> get ( 'bar' ), '->get() returns the service for the given id' );
$this -> assertEquals ( $sc -> __foo_bar , $sc -> get ( 'foo_bar' ), '->get() returns the service if a get*Method() is defined' );
$this -> assertEquals ( $sc -> __foo_baz , $sc -> get ( 'foo.baz' ), '->get() returns the service if a get*Method() is defined' );
2010-05-06 12:25:53 +01:00
2010-06-27 17:28:29 +01:00
$sc -> set ( 'bar' , $bar = new \stdClass ());
2011-02-19 18:30:12 +00:00
$this -> assertEquals ( $bar , $sc -> get ( 'bar' ), '->get() prefers to return a service defined with set() than one defined with a getXXXMethod()' );
2010-05-06 12:25:53 +01:00
2010-05-07 15:09:11 +01:00
try {
2010-06-27 17:28:29 +01:00
$sc -> get ( '' );
$this -> fail ( '->get() throws a \InvalidArgumentException exception if the service is empty' );
2010-05-07 15:09:11 +01:00
} catch ( \Exception $e ) {
2010-06-27 17:28:29 +01:00
$this -> assertInstanceOf ( '\InvalidArgumentException' , $e , '->get() throws a \InvalidArgumentException exception if the service is empty' );
$this -> assertEquals ( 'The service "" does not exist.' , $e -> getMessage (), '->get() throws a \InvalidArgumentException exception if the service is empty' );
2010-05-06 12:25:53 +01:00
}
2010-06-27 17:28:29 +01:00
$this -> assertNull ( $sc -> get ( '' , ContainerInterface :: NULL_ON_INVALID_REFERENCE ));
2010-03-18 07:48:03 +00:00
}
2011-02-19 18:30:12 +00:00
public function testGetCircularReference ()
{
$sc = new ProjectServiceContainer ();
try {
$sc -> get ( 'circular' );
2011-03-14 20:12:42 +00:00
$this -> fail ( '->get() throws a CircularReferenceException if it contains circular reference' );
2011-02-19 18:30:12 +00:00
} catch ( \Exception $e ) {
2011-03-14 20:12:42 +00:00
$this -> assertInstanceOf ( '\Symfony\Component\DependencyInjection\Exception\CircularReferenceException' , $e , '->get() throws a CircularReferenceException if it contains circular reference' );
2011-02-19 18:30:12 +00:00
$this -> assertStringStartsWith ( 'Circular reference detected for service "circular"' , $e -> getMessage (), '->get() throws a \LogicException if it contains circular reference' );
}
}
2010-06-27 17:28:29 +01:00
/**
2010-08-20 22:09:55 +01:00
* @ covers Symfony\Component\DependencyInjection\Container :: has
2010-06-27 17:28:29 +01:00
*/
public function testHas ()
2010-03-18 07:48:03 +00:00
{
2010-06-27 17:28:29 +01:00
$sc = new ProjectServiceContainer ();
$sc -> set ( 'foo' , new \stdClass ());
$this -> assertFalse ( $sc -> has ( 'foo1' ), '->has() returns false if the service does not exist' );
$this -> assertTrue ( $sc -> has ( 'foo' ), '->has() returns true if the service exists' );
$this -> assertTrue ( $sc -> has ( 'bar' ), '->has() returns true if a get*Method() is defined' );
$this -> assertTrue ( $sc -> has ( 'foo_bar' ), '->has() returns true if a get*Method() is defined' );
$this -> assertTrue ( $sc -> has ( 'foo.baz' ), '->has() returns true if a get*Method() is defined' );
2010-03-18 07:48:03 +00:00
}
2011-01-17 22:28:59 +00:00
public function testEnterLeaveCurrentScope ()
{
$container = new ProjectServiceContainer ();
2011-02-13 09:33:53 +00:00
$container -> addScope ( new Scope ( 'foo' ));
2011-01-17 22:28:59 +00:00
$container -> enterScope ( 'foo' );
$scoped1 = $container -> get ( 'scoped' );
$scopedFoo1 = $container -> get ( 'scoped_foo' );
$container -> enterScope ( 'foo' );
$scoped2 = $container -> get ( 'scoped' );
$scoped3 = $container -> get ( 'scoped' );
$scopedFoo2 = $container -> get ( 'scoped_foo' );
$container -> leaveScope ( 'foo' );
$scoped4 = $container -> get ( 'scoped' );
$scopedFoo3 = $container -> get ( 'scoped_foo' );
$this -> assertNotSame ( $scoped1 , $scoped2 );
$this -> assertSame ( $scoped2 , $scoped3 );
$this -> assertSame ( $scoped1 , $scoped4 );
$this -> assertNotSame ( $scopedFoo1 , $scopedFoo2 );
$this -> assertSame ( $scopedFoo1 , $scopedFoo3 );
}
public function testEnterLeaveScopeWithChildScopes ()
{
$container = new Container ();
2011-02-13 09:33:53 +00:00
$container -> addScope ( new Scope ( 'foo' ));
$container -> addScope ( new Scope ( 'bar' , 'foo' ));
2011-01-17 22:28:59 +00:00
$this -> assertFalse ( $container -> isScopeActive ( 'foo' ));
$container -> enterScope ( 'foo' );
$container -> enterScope ( 'bar' );
$this -> assertTrue ( $container -> isScopeActive ( 'foo' ));
$this -> assertFalse ( $container -> has ( 'a' ));
$a = new \stdClass ();
$container -> set ( 'a' , $a , 'bar' );
$services = $this -> getField ( $container , 'scopedServices' );
$this -> assertTrue ( isset ( $services [ 'bar' ][ 'a' ]));
$this -> assertSame ( $a , $services [ 'bar' ][ 'a' ]);
$this -> assertTrue ( $container -> has ( 'a' ));
$container -> leaveScope ( 'foo' );
$services = $this -> getField ( $container , 'scopedServices' );
$this -> assertFalse ( isset ( $services [ 'bar' ]));
$this -> assertFalse ( $container -> isScopeActive ( 'foo' ));
$this -> assertFalse ( $container -> has ( 'a' ));
}
2011-02-19 18:30:12 +00:00
public function testLeaveScopeNotActive ()
{
$container = new Container ();
$container -> addScope ( new Scope ( 'foo' ));
try {
$container -> leaveScope ( 'foo' );
$this -> fail ( '->leaveScope() throws a \LogicException if the scope is not active yet' );
} catch ( \Exception $e ) {
$this -> assertInstanceOf ( '\LogicException' , $e , '->leaveScope() throws a \LogicException if the scope is not active yet' );
$this -> assertEquals ( 'The scope "foo" is not active.' , $e -> getMessage (), '->leaveScope() throws a \LogicException if the scope is not active yet' );
}
try {
$container -> leaveScope ( 'bar' );
$this -> fail ( '->leaveScope() throws a \LogicException if the scope does not exist' );
} catch ( \Exception $e ) {
$this -> assertInstanceOf ( '\LogicException' , $e , '->leaveScope() throws a \LogicException if the scope does not exist' );
$this -> assertEquals ( 'The scope "bar" is not active.' , $e -> getMessage (), '->leaveScope() throws a \LogicException if the scope does not exist' );
}
}
2011-01-17 22:28:59 +00:00
/**
* @ expectedException \InvalidArgumentException
* @ dataProvider getBuiltInScopes
*/
public function testAddScopeDoesNotAllowBuiltInScopes ( $scope )
{
$container = new Container ();
2011-02-13 09:33:53 +00:00
$container -> addScope ( new Scope ( $scope ));
2011-01-17 22:28:59 +00:00
}
/**
* @ expectedException \InvalidArgumentException
*/
public function testAddScopeDoesNotAllowExistingScope ()
{
$container = new Container ();
2011-02-13 09:33:53 +00:00
$container -> addScope ( new Scope ( 'foo' ));
$container -> addScope ( new Scope ( 'foo' ));
2011-01-17 22:28:59 +00:00
}
/**
* @ expectedException \InvalidArgumentException
* @ dataProvider getInvalidParentScopes
*/
public function testAddScopeDoesNotAllowInvalidParentScope ( $scope )
{
$c = new Container ();
2011-02-13 09:33:53 +00:00
$c -> addScope ( new Scope ( 'foo' , $scope ));
2011-01-17 22:28:59 +00:00
}
public function testAddScope ()
{
$c = new Container ();
2011-02-13 09:33:53 +00:00
$c -> addScope ( new Scope ( 'foo' ));
$c -> addScope ( new Scope ( 'bar' , 'foo' ));
2011-01-17 22:28:59 +00:00
$this -> assertSame ( array ( 'foo' => 'container' , 'bar' => 'foo' ), $this -> getField ( $c , 'scopes' ));
$this -> assertSame ( array ( 'foo' => array ( 'bar' ), 'bar' => array ()), $this -> getField ( $c , 'scopeChildren' ));
}
public function testHasScope ()
{
$c = new Container ();
$this -> assertFalse ( $c -> hasScope ( 'foo' ));
2011-02-13 09:33:53 +00:00
$c -> addScope ( new Scope ( 'foo' ));
2011-01-17 22:28:59 +00:00
$this -> assertTrue ( $c -> hasScope ( 'foo' ));
}
public function testIsScopeActive ()
{
$c = new Container ();
$this -> assertFalse ( $c -> isScopeActive ( 'foo' ));
2011-02-13 09:33:53 +00:00
$c -> addScope ( new Scope ( 'foo' ));
2011-01-17 22:28:59 +00:00
$this -> assertFalse ( $c -> isScopeActive ( 'foo' ));
$c -> enterScope ( 'foo' );
$this -> assertTrue ( $c -> isScopeActive ( 'foo' ));
$c -> leaveScope ( 'foo' );
$this -> assertFalse ( $c -> isScopeActive ( 'foo' ));
}
2011-03-09 14:38:02 +00:00
public function testGetThrowsException ()
{
$c = new ProjectServiceContainer ();
try {
$c -> get ( 'throw_exception' );
$this -> fail ();
} catch ( \Exception $e ) {
$this -> assertEquals ( 'Something went terribly wrong!' , $e -> getMessage ());
}
try {
$c -> get ( 'throw_exception' );
$this -> fail ();
} catch ( \Exception $e ) {
$this -> assertEquals ( 'Something went terribly wrong!' , $e -> getMessage ());
}
}
2011-01-17 22:28:59 +00:00
public function getInvalidParentScopes ()
{
return array (
array ( ContainerInterface :: SCOPE_PROTOTYPE ),
array ( 'bar' ),
);
}
public function getBuiltInScopes ()
{
return array (
array ( ContainerInterface :: SCOPE_CONTAINER ),
array ( ContainerInterface :: SCOPE_PROTOTYPE ),
);
}
protected function getField ( $obj , $field )
{
$reflection = new \ReflectionProperty ( $obj , $field );
$reflection -> setAccessible ( true );
return $reflection -> getValue ( $obj );
}
2010-05-06 12:25:53 +01:00
}
2010-03-18 07:48:03 +00:00
2010-05-06 12:25:53 +01:00
class ProjectServiceContainer extends Container
{
public $__bar , $__foo_bar , $__foo_baz ;
2010-03-18 07:48:03 +00:00
2010-05-06 12:25:53 +01:00
public function __construct ()
2010-03-18 07:48:03 +00:00
{
2010-05-06 12:25:53 +01:00
parent :: __construct ();
$this -> __bar = new \stdClass ();
$this -> __foo_bar = new \stdClass ();
$this -> __foo_baz = new \stdClass ();
2010-03-18 07:48:03 +00:00
}
2010-05-06 12:25:53 +01:00
2011-01-17 22:28:59 +00:00
protected function getScopedService ()
{
if ( ! isset ( $this -> scopedServices [ 'foo' ])) {
throw new \RuntimeException ( 'Invalid call' );
}
return $this -> services [ 'scoped' ] = $this -> scopedServices [ 'foo' ][ 'scoped' ] = new \stdClass ();
}
protected function getScopedFooService ()
{
if ( ! isset ( $this -> scopedServices [ 'foo' ])) {
throw new \RuntimeException ( 'invalid call' );
}
return $this -> services [ 'scoped_foo' ] = $this -> scopedServices [ 'foo' ][ 'scoped_foo' ] = new \stdClass ();
}
2010-05-06 12:25:53 +01:00
protected function getBarService ()
2010-03-18 07:48:03 +00:00
{
2010-05-06 12:25:53 +01:00
return $this -> __bar ;
2010-03-18 07:48:03 +00:00
}
2010-03-25 13:04:48 +00:00
2010-05-06 12:25:53 +01:00
protected function getFooBarService ()
2010-03-25 13:04:48 +00:00
{
2010-05-06 12:25:53 +01:00
return $this -> __foo_bar ;
2010-03-25 13:04:48 +00:00
}
2010-05-06 12:25:53 +01:00
protected function getFoo_BazService ()
2010-03-25 13:04:48 +00:00
{
2010-05-06 12:25:53 +01:00
return $this -> __foo_baz ;
2010-03-25 13:04:48 +00:00
}
2011-02-19 18:30:12 +00:00
2011-02-19 18:33:39 +00:00
protected function getCircularService ()
{
2011-02-19 18:30:12 +00:00
return $this -> get ( 'circular' );
}
2011-03-09 14:38:02 +00:00
protected function getThrowExceptionService ()
{
throw new \Exception ( 'Something went terribly wrong!' );
}
2010-03-18 07:48:03 +00:00
}