| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724 |
- <?php
- namespace Illuminate\Tests\Container;
- use Illuminate\Container\Container;
- use Illuminate\Container\EntryNotFoundException;
- use Illuminate\Contracts\Container\BindingResolutionException;
- use Illuminate\Contracts\Container\CircularDependencyException;
- use PHPUnit\Framework\TestCase;
- use Psr\Container\ContainerExceptionInterface;
- use stdClass;
- use TypeError;
- class ContainerTest extends TestCase
- {
- protected function tearDown(): void
- {
- Container::setInstance(null);
- }
- public function testContainerSingleton()
- {
- $container = Container::setInstance(new Container);
- $this->assertSame($container, Container::getInstance());
- Container::setInstance(null);
- $container2 = Container::getInstance();
- $this->assertInstanceOf(Container::class, $container2);
- $this->assertNotSame($container, $container2);
- }
- public function testClosureResolution()
- {
- $container = new Container;
- $container->bind('name', function () {
- return 'Taylor';
- });
- $this->assertSame('Taylor', $container->make('name'));
- }
- public function testBindIfDoesntRegisterIfServiceAlreadyRegistered()
- {
- $container = new Container;
- $container->bind('name', function () {
- return 'Taylor';
- });
- $container->bindIf('name', function () {
- return 'Dayle';
- });
- $this->assertSame('Taylor', $container->make('name'));
- }
- public function testBindIfDoesRegisterIfServiceNotRegisteredYet()
- {
- $container = new Container;
- $container->bind('surname', function () {
- return 'Taylor';
- });
- $container->bindIf('name', function () {
- return 'Dayle';
- });
- $this->assertSame('Dayle', $container->make('name'));
- }
- public function testSingletonIfDoesntRegisterIfBindingAlreadyRegistered()
- {
- $container = new Container;
- $container->singleton('class', function () {
- return new stdClass;
- });
- $firstInstantiation = $container->make('class');
- $container->singletonIf('class', function () {
- return new ContainerConcreteStub;
- });
- $secondInstantiation = $container->make('class');
- $this->assertSame($firstInstantiation, $secondInstantiation);
- }
- public function testSingletonIfDoesRegisterIfBindingNotRegisteredYet()
- {
- $container = new Container;
- $container->singleton('class', function () {
- return new stdClass;
- });
- $container->singletonIf('otherClass', function () {
- return new ContainerConcreteStub;
- });
- $firstInstantiation = $container->make('otherClass');
- $secondInstantiation = $container->make('otherClass');
- $this->assertSame($firstInstantiation, $secondInstantiation);
- }
- public function testSharedClosureResolution()
- {
- $container = new Container;
- $container->singleton('class', function () {
- return new stdClass;
- });
- $firstInstantiation = $container->make('class');
- $secondInstantiation = $container->make('class');
- $this->assertSame($firstInstantiation, $secondInstantiation);
- }
- public function testScopedClosureResolution()
- {
- $container = new Container;
- $container->scoped('class', function () {
- return new stdClass;
- });
- $firstInstantiation = $container->make('class');
- $secondInstantiation = $container->make('class');
- $this->assertSame($firstInstantiation, $secondInstantiation);
- }
- public function testScopedClosureResets()
- {
- $container = new Container;
- $container->scoped('class', function () {
- return new stdClass;
- });
- $firstInstantiation = $container->make('class');
- $container->forgetScopedInstances();
- $secondInstantiation = $container->make('class');
- $this->assertNotSame($firstInstantiation, $secondInstantiation);
- }
- public function testAutoConcreteResolution()
- {
- $container = new Container;
- $this->assertInstanceOf(ContainerConcreteStub::class, $container->make(ContainerConcreteStub::class));
- }
- public function testSharedConcreteResolution()
- {
- $container = new Container;
- $container->singleton(ContainerConcreteStub::class);
- $var1 = $container->make(ContainerConcreteStub::class);
- $var2 = $container->make(ContainerConcreteStub::class);
- $this->assertSame($var1, $var2);
- }
- public function testScopedConcreteResolutionResets()
- {
- $container = new Container;
- $container->scoped(ContainerConcreteStub::class);
- $var1 = $container->make(ContainerConcreteStub::class);
- $container->forgetScopedInstances();
- $var2 = $container->make(ContainerConcreteStub::class);
- $this->assertNotSame($var1, $var2);
- }
- public function testBindFailsLoudlyWithInvalidArgument()
- {
- $this->expectException(TypeError::class);
- $container = new Container;
- $concrete = new ContainerConcreteStub;
- $container->bind(ContainerConcreteStub::class, $concrete);
- }
- public function testAbstractToConcreteResolution()
- {
- $container = new Container;
- $container->bind(IContainerContractStub::class, ContainerImplementationStub::class);
- $class = $container->make(ContainerDependentStub::class);
- $this->assertInstanceOf(ContainerImplementationStub::class, $class->impl);
- }
- public function testNestedDependencyResolution()
- {
- $container = new Container;
- $container->bind(IContainerContractStub::class, ContainerImplementationStub::class);
- $class = $container->make(ContainerNestedDependentStub::class);
- $this->assertInstanceOf(ContainerDependentStub::class, $class->inner);
- $this->assertInstanceOf(ContainerImplementationStub::class, $class->inner->impl);
- }
- public function testContainerIsPassedToResolvers()
- {
- $container = new Container;
- $container->bind('something', function ($c) {
- return $c;
- });
- $c = $container->make('something');
- $this->assertSame($c, $container);
- }
- public function testArrayAccess()
- {
- $container = new Container;
- $container['something'] = function () {
- return 'foo';
- };
- $this->assertTrue(isset($container['something']));
- $this->assertSame('foo', $container['something']);
- unset($container['something']);
- $this->assertFalse(isset($container['something']));
- }
- public function testAliases()
- {
- $container = new Container;
- $container['foo'] = 'bar';
- $container->alias('foo', 'baz');
- $container->alias('baz', 'bat');
- $this->assertSame('bar', $container->make('foo'));
- $this->assertSame('bar', $container->make('baz'));
- $this->assertSame('bar', $container->make('bat'));
- }
- public function testAliasesWithArrayOfParameters()
- {
- $container = new Container;
- $container->bind('foo', function ($app, $config) {
- return $config;
- });
- $container->alias('foo', 'baz');
- $this->assertEquals([1, 2, 3], $container->make('baz', [1, 2, 3]));
- }
- public function testBindingsCanBeOverridden()
- {
- $container = new Container;
- $container['foo'] = 'bar';
- $container['foo'] = 'baz';
- $this->assertSame('baz', $container['foo']);
- }
- public function testBindingAnInstanceReturnsTheInstance()
- {
- $container = new Container;
- $bound = new stdClass;
- $resolved = $container->instance('foo', $bound);
- $this->assertSame($bound, $resolved);
- }
- public function testBindingAnInstanceAsShared()
- {
- $container = new Container;
- $bound = new stdClass;
- $container->instance('foo', $bound);
- $object = $container->make('foo');
- $this->assertSame($bound, $object);
- }
- public function testResolutionOfDefaultParameters()
- {
- $container = new Container;
- $instance = $container->make(ContainerDefaultValueStub::class);
- $this->assertInstanceOf(ContainerConcreteStub::class, $instance->stub);
- $this->assertSame('taylor', $instance->default);
- }
- public function testUnsetRemoveBoundInstances()
- {
- $container = new Container;
- $container->instance('object', new stdClass);
- unset($container['object']);
- $this->assertFalse($container->bound('object'));
- }
- public function testBoundInstanceAndAliasCheckViaArrayAccess()
- {
- $container = new Container;
- $container->instance('object', new stdClass);
- $container->alias('object', 'alias');
- $this->assertTrue(isset($container['object']));
- $this->assertTrue(isset($container['alias']));
- }
- public function testReboundListeners()
- {
- unset($_SERVER['__test.rebind']);
- $container = new Container;
- $container->bind('foo', function () {
- //
- });
- $container->rebinding('foo', function () {
- $_SERVER['__test.rebind'] = true;
- });
- $container->bind('foo', function () {
- //
- });
- $this->assertTrue($_SERVER['__test.rebind']);
- }
- public function testReboundListenersOnInstances()
- {
- unset($_SERVER['__test.rebind']);
- $container = new Container;
- $container->instance('foo', function () {
- //
- });
- $container->rebinding('foo', function () {
- $_SERVER['__test.rebind'] = true;
- });
- $container->instance('foo', function () {
- //
- });
- $this->assertTrue($_SERVER['__test.rebind']);
- }
- public function testReboundListenersOnInstancesOnlyFiresIfWasAlreadyBound()
- {
- $_SERVER['__test.rebind'] = false;
- $container = new Container;
- $container->rebinding('foo', function () {
- $_SERVER['__test.rebind'] = true;
- });
- $container->instance('foo', function () {
- //
- });
- $this->assertFalse($_SERVER['__test.rebind']);
- }
- public function testInternalClassWithDefaultParameters()
- {
- $this->expectException(BindingResolutionException::class);
- $this->expectExceptionMessage('Unresolvable dependency resolving [Parameter #0 [ <required> $first ]] in class Illuminate\Tests\Container\ContainerMixedPrimitiveStub');
- $container = new Container;
- $container->make(ContainerMixedPrimitiveStub::class, []);
- }
- public function testBindingResolutionExceptionMessage()
- {
- $this->expectException(BindingResolutionException::class);
- $this->expectExceptionMessage('Target [Illuminate\Tests\Container\IContainerContractStub] is not instantiable.');
- $container = new Container;
- $container->make(IContainerContractStub::class, []);
- }
- public function testBindingResolutionExceptionMessageIncludesBuildStack()
- {
- $this->expectException(BindingResolutionException::class);
- $this->expectExceptionMessage('Target [Illuminate\Tests\Container\IContainerContractStub] is not instantiable while building [Illuminate\Tests\Container\ContainerDependentStub].');
- $container = new Container;
- $container->make(ContainerDependentStub::class, []);
- }
- public function testBindingResolutionExceptionMessageWhenClassDoesNotExist()
- {
- $this->expectException(BindingResolutionException::class);
- $this->expectExceptionMessage('Target class [Foo\Bar\Baz\DummyClass] does not exist.');
- $container = new Container;
- $container->build('Foo\Bar\Baz\DummyClass');
- }
- public function testForgetInstanceForgetsInstance()
- {
- $container = new Container;
- $containerConcreteStub = new ContainerConcreteStub;
- $container->instance(ContainerConcreteStub::class, $containerConcreteStub);
- $this->assertTrue($container->isShared(ContainerConcreteStub::class));
- $container->forgetInstance(ContainerConcreteStub::class);
- $this->assertFalse($container->isShared(ContainerConcreteStub::class));
- }
- public function testForgetInstancesForgetsAllInstances()
- {
- $container = new Container;
- $containerConcreteStub1 = new ContainerConcreteStub;
- $containerConcreteStub2 = new ContainerConcreteStub;
- $containerConcreteStub3 = new ContainerConcreteStub;
- $container->instance('Instance1', $containerConcreteStub1);
- $container->instance('Instance2', $containerConcreteStub2);
- $container->instance('Instance3', $containerConcreteStub3);
- $this->assertTrue($container->isShared('Instance1'));
- $this->assertTrue($container->isShared('Instance2'));
- $this->assertTrue($container->isShared('Instance3'));
- $container->forgetInstances();
- $this->assertFalse($container->isShared('Instance1'));
- $this->assertFalse($container->isShared('Instance2'));
- $this->assertFalse($container->isShared('Instance3'));
- }
- public function testContainerFlushFlushesAllBindingsAliasesAndResolvedInstances()
- {
- $container = new Container;
- $container->bind('ConcreteStub', function () {
- return new ContainerConcreteStub;
- }, true);
- $container->alias('ConcreteStub', 'ContainerConcreteStub');
- $container->make('ConcreteStub');
- $this->assertTrue($container->resolved('ConcreteStub'));
- $this->assertTrue($container->isAlias('ContainerConcreteStub'));
- $this->assertArrayHasKey('ConcreteStub', $container->getBindings());
- $this->assertTrue($container->isShared('ConcreteStub'));
- $container->flush();
- $this->assertFalse($container->resolved('ConcreteStub'));
- $this->assertFalse($container->isAlias('ContainerConcreteStub'));
- $this->assertEmpty($container->getBindings());
- $this->assertFalse($container->isShared('ConcreteStub'));
- }
- public function testResolvedResolvesAliasToBindingNameBeforeChecking()
- {
- $container = new Container;
- $container->bind('ConcreteStub', function () {
- return new ContainerConcreteStub;
- }, true);
- $container->alias('ConcreteStub', 'foo');
- $this->assertFalse($container->resolved('ConcreteStub'));
- $this->assertFalse($container->resolved('foo'));
- $container->make('ConcreteStub');
- $this->assertTrue($container->resolved('ConcreteStub'));
- $this->assertTrue($container->resolved('foo'));
- }
- public function testGetAlias()
- {
- $container = new Container;
- $container->alias('ConcreteStub', 'foo');
- $this->assertSame('ConcreteStub', $container->getAlias('foo'));
- }
- public function testItThrowsExceptionWhenAbstractIsSameAsAlias()
- {
- $this->expectException('LogicException');
- $this->expectExceptionMessage('[name] is aliased to itself.');
- $container = new Container;
- $container->alias('name', 'name');
- }
- public function testContainerGetFactory()
- {
- $container = new Container;
- $container->bind('name', function () {
- return 'Taylor';
- });
- $factory = $container->factory('name');
- $this->assertEquals($container->make('name'), $factory());
- }
- public function testMakeWithMethodIsAnAliasForMakeMethod()
- {
- $mock = $this->getMockBuilder(Container::class)
- ->onlyMethods(['make'])
- ->getMock();
- $mock->expects($this->once())
- ->method('make')
- ->with(ContainerDefaultValueStub::class, ['default' => 'laurence'])
- ->willReturn(new stdClass);
- $result = $mock->makeWith(ContainerDefaultValueStub::class, ['default' => 'laurence']);
- $this->assertInstanceOf(stdClass::class, $result);
- }
- public function testResolvingWithArrayOfParameters()
- {
- $container = new Container;
- $instance = $container->make(ContainerDefaultValueStub::class, ['default' => 'adam']);
- $this->assertSame('adam', $instance->default);
- $instance = $container->make(ContainerDefaultValueStub::class);
- $this->assertSame('taylor', $instance->default);
- $container->bind('foo', function ($app, $config) {
- return $config;
- });
- $this->assertEquals([1, 2, 3], $container->make('foo', [1, 2, 3]));
- }
- public function testResolvingWithUsingAnInterface()
- {
- $container = new Container;
- $container->bind(IContainerContractStub::class, ContainerInjectVariableStubWithInterfaceImplementation::class);
- $instance = $container->make(IContainerContractStub::class, ['something' => 'laurence']);
- $this->assertSame('laurence', $instance->something);
- }
- public function testNestedParameterOverride()
- {
- $container = new Container;
- $container->bind('foo', function ($app, $config) {
- return $app->make('bar', ['name' => 'Taylor']);
- });
- $container->bind('bar', function ($app, $config) {
- return $config;
- });
- $this->assertEquals(['name' => 'Taylor'], $container->make('foo', ['something']));
- }
- public function testNestedParametersAreResetForFreshMake()
- {
- $container = new Container;
- $container->bind('foo', function ($app, $config) {
- return $app->make('bar');
- });
- $container->bind('bar', function ($app, $config) {
- return $config;
- });
- $this->assertEquals([], $container->make('foo', ['something']));
- }
- public function testSingletonBindingsNotRespectedWithMakeParameters()
- {
- $container = new Container;
- $container->singleton('foo', function ($app, $config) {
- return $config;
- });
- $this->assertEquals(['name' => 'taylor'], $container->make('foo', ['name' => 'taylor']));
- $this->assertEquals(['name' => 'abigail'], $container->make('foo', ['name' => 'abigail']));
- }
- public function testCanBuildWithoutParameterStackWithNoConstructors()
- {
- $container = new Container;
- $this->assertInstanceOf(ContainerConcreteStub::class, $container->build(ContainerConcreteStub::class));
- }
- public function testCanBuildWithoutParameterStackWithConstructors()
- {
- $container = new Container;
- $container->bind(IContainerContractStub::class, ContainerImplementationStub::class);
- $this->assertInstanceOf(ContainerDependentStub::class, $container->build(ContainerDependentStub::class));
- }
- public function testContainerKnowsEntry()
- {
- $container = new Container;
- $container->bind(IContainerContractStub::class, ContainerImplementationStub::class);
- $this->assertTrue($container->has(IContainerContractStub::class));
- }
- public function testContainerCanBindAnyWord()
- {
- $container = new Container;
- $container->bind('Taylor', stdClass::class);
- $this->assertInstanceOf(stdClass::class, $container->get('Taylor'));
- }
- public function testContainerCanDynamicallySetService()
- {
- $container = new Container;
- $this->assertFalse(isset($container['name']));
- $container['name'] = 'Taylor';
- $this->assertTrue(isset($container['name']));
- $this->assertSame('Taylor', $container['name']);
- }
- public function testUnknownEntryThrowsException()
- {
- $this->expectException(EntryNotFoundException::class);
- $container = new Container;
- $container->get('Taylor');
- }
- public function testBoundEntriesThrowsContainerExceptionWhenNotResolvable()
- {
- $this->expectException(ContainerExceptionInterface::class);
- $container = new Container;
- $container->bind('Taylor', IContainerContractStub::class);
- $container->get('Taylor');
- }
- public function testContainerCanResolveClasses()
- {
- $container = new Container;
- $class = $container->get(ContainerConcreteStub::class);
- $this->assertInstanceOf(ContainerConcreteStub::class, $class);
- }
- // public function testContainerCanCatchCircularDependency()
- // {
- // $this->expectException(CircularDependencyException::class);
- // $container = new Container;
- // $container->get(CircularAStub::class);
- // }
- }
- class CircularAStub
- {
- public function __construct(CircularBStub $b)
- {
- //
- }
- }
- class CircularBStub
- {
- public function __construct(CircularCStub $c)
- {
- //
- }
- }
- class CircularCStub
- {
- public function __construct(CircularAStub $a)
- {
- //
- }
- }
- class ContainerConcreteStub
- {
- //
- }
- interface IContainerContractStub
- {
- //
- }
- class ContainerImplementationStub implements IContainerContractStub
- {
- //
- }
- class ContainerImplementationStubTwo implements IContainerContractStub
- {
- //
- }
- class ContainerDependentStub
- {
- public $impl;
- public function __construct(IContainerContractStub $impl)
- {
- $this->impl = $impl;
- }
- }
- class ContainerNestedDependentStub
- {
- public $inner;
- public function __construct(ContainerDependentStub $inner)
- {
- $this->inner = $inner;
- }
- }
- class ContainerDefaultValueStub
- {
- public $stub;
- public $default;
- public function __construct(ContainerConcreteStub $stub, $default = 'taylor')
- {
- $this->stub = $stub;
- $this->default = $default;
- }
- }
- class ContainerMixedPrimitiveStub
- {
- public $first;
- public $last;
- public $stub;
- public function __construct($first, ContainerConcreteStub $stub, $last)
- {
- $this->stub = $stub;
- $this->last = $last;
- $this->first = $first;
- }
- }
- class ContainerInjectVariableStub
- {
- public $something;
- public function __construct(ContainerConcreteStub $concrete, $something)
- {
- $this->something = $something;
- }
- }
- class ContainerInjectVariableStubWithInterfaceImplementation implements IContainerContractStub
- {
- public $something;
- public function __construct(ContainerConcreteStub $concrete, $something)
- {
- $this->something = $something;
- }
- }
|