* * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Tests; use PHPUnit\Framework\TestCase; use Symfony\Component\DependencyInjection\Container; use Symfony\Component\DependencyInjection\ServiceLocator; use Symfony\Component\DependencyInjection\ServiceSubscriberInterface; class ServiceLocatorTest extends TestCase { public function testHas() { $locator = new ServiceLocator(array( 'foo' => function () { return 'bar'; }, 'bar' => function () { return 'baz'; }, function () { return 'dummy'; }, )); $this->assertTrue($locator->has('foo')); $this->assertTrue($locator->has('bar')); $this->assertFalse($locator->has('dummy')); } public function testGet() { $locator = new ServiceLocator(array( 'foo' => function () { return 'bar'; }, 'bar' => function () { return 'baz'; }, )); $this->assertSame('bar', $locator->get('foo')); $this->assertSame('baz', $locator->get('bar')); } public function testGetDoesNotMemoize() { $i = 0; $locator = new ServiceLocator(array( 'foo' => function () use (&$i) { ++$i; return 'bar'; }, )); $this->assertSame('bar', $locator->get('foo')); $this->assertSame('bar', $locator->get('foo')); $this->assertSame(2, $i); } /** * @expectedException \Psr\Container\NotFoundExceptionInterface * @expectedExceptionMessage Service "dummy" not found: the container inside "Symfony\Component\DependencyInjection\Tests\ServiceLocatorTest" is a smaller service locator that only knows about the "foo" and "bar" services. */ public function testGetThrowsOnUndefinedService() { $locator = new ServiceLocator(array( 'foo' => function () { return 'bar'; }, 'bar' => function () { return 'baz'; }, )); $locator->get('dummy'); } /** * @expectedException \Psr\Container\NotFoundExceptionInterface * @expectedExceptionMessage The service "foo" has a dependency on a non-existent service "bar". This locator only knows about the "foo" service. */ public function testThrowsOnUndefinedInternalService() { $locator = new ServiceLocator(array( 'foo' => function () use (&$locator) { return $locator->get('bar'); }, )); $locator->get('foo'); } /** * @expectedException \Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException * @expectedExceptionMessage Circular reference detected for service "bar", path: "bar -> baz -> bar". */ public function testThrowsOnCircularReference() { $locator = new ServiceLocator(array( 'foo' => function () use (&$locator) { return $locator->get('bar'); }, 'bar' => function () use (&$locator) { return $locator->get('baz'); }, 'baz' => function () use (&$locator) { return $locator->get('bar'); }, )); $locator->get('foo'); } /** * @expectedException \Psr\Container\NotFoundExceptionInterface * @expectedExceptionMessage Service "foo" not found: even though it exists in the app's container, the container inside "caller" is a smaller service locator that only knows about the "bar" service. Unless you need extra laziness, try using dependency injection instead. Otherwise, you need to declare it using "SomeServiceSubscriber::getSubscribedServices()". */ public function testThrowsInServiceSubscriber() { $container = new Container(); $container->set('foo', new \stdClass()); $subscriber = new SomeServiceSubscriber(); $subscriber->container = new ServiceLocator(array('bar' => function () {})); $subscriber->container = $subscriber->container->withContext('caller', $container); $subscriber->getFoo(); } public function testInvoke() { $locator = new ServiceLocator(array( 'foo' => function () { return 'bar'; }, 'bar' => function () { return 'baz'; }, )); $this->assertSame('bar', $locator('foo')); $this->assertSame('baz', $locator('bar')); $this->assertNull($locator('dummy'), '->__invoke() should return null on invalid service'); } } class SomeServiceSubscriber implements ServiceSubscriberinterface { public $container; public function getFoo() { return $this->container->get('foo'); } public static function getSubscribedServices() { return array('bar' => 'stdClass'); } }