<?php // DependenciesTest.php // Created: 2025-01-21 // Updated: 2025-03-21 declare(strict_types=1); namespace { use PHPUnit\Framework\TestCase; use PHPUnit\Framework\Attributes\{CoversClass,UsesClass}; use Index\Dependencies; #[CoversClass(Dependencies::class)] final class DependenciesTest extends TestCase { public function testDependencyCall(): void { $deps = new Dependencies; $deps->register(\Index\Db\DbResultIterator::class, construct: fn($result) => null); $deps->register(\Index\Db\NullDb\NullDbResult::class); $func = function( \Index\Db\DbResult $result, string $soup, ?\Index\Db\DbConnection $conn, string $named = '', ?\Index\Db\NullDb\NullDbTransaction $transaction = null ) { return $result instanceof \Index\Db\NullDb\NullDbResult && $soup === 'beans' && $conn === null && $named === 'bowl' && $transaction === null; }; $this->assertTrue($deps->call($func, 'beans', named: 'bowl')); $outOfOrder = function( string $soup, \Index\Db\DbResult $result, string $named = '', ?\Index\Db\DbResultIterator $iterator = null ) { return $result instanceof \Index\Db\NullDb\NullDbResult && $soup === 'beans' && $named === 'bowl' && $iterator instanceof \Index\Db\DbResultIterator; }; $this->assertTrue($deps->call($outOfOrder, 'beans', named: 'bowl')); } public function testDependencyResolver(): void { $deps = new Dependencies; $deps->register(\Index\Db\DbResultIterator::class, construct: fn($result) => null); $deps->register(\Index\Db\NullDb\NullDbResult::class); $iterator = $deps->resolve(\Index\Db\DbResultIterator::class); $this->assertInstanceOf(\Index\Db\DbResultIterator::class, $iterator); $this->assertFalse($iterator->valid()); $result = $deps->resolve(\Index\Db\NullDb\NullDbResult::class); $this->assertInstanceOf(\Index\Db\DbResult::class, $result); } public function testRequiredDependency(): void { $this->expectException(TypeError::class); $deps = new Dependencies; $deps->register(DependenciesTest\RequiredParamTestClass::class); $deps->resolve(DependenciesTest\RequiredParamTestClass::class); $instance = $deps->resolve(DependenciesTest\RequiredParamTestClass::class); $this->assertInstanceOf(DependenciesTest\RequiredParamTestClass::class, $instance); // this is the one that actually triggers the exception because of lazy instantiation $this->assertInstanceOf(DependenciesTest\RequiredParamTestClass::class, $instance->test); } public function testNullableDependency(): void { $deps = new Dependencies; $deps->register(DependenciesTest\NullableParamTestClass::class); $instance = $deps->resolve(DependenciesTest\NullableParamTestClass::class); $this->assertInstanceOf(DependenciesTest\NullableParamTestClass::class, $instance); $this->assertNull($instance->test); } public function testFetchAllDependencies(): void { $deps = new Dependencies; $deps->register(\Index\Db\NullDb\NullDbResult::class); $deps->register(DependenciesTest\NullableParamTestClass::class); $deps->register(DependenciesTest\Routes1::class); $deps->register(new DependenciesTest\Routes2); $deps->register(DependenciesTest\RequiredParamTestClass::class); $deps->register(DependenciesTest\Routes3::class); $deps->register(\Index\Db\DbResultIterator::class, construct: fn($result) => null); $routes3 = $deps->resolve(\Index\Http\Routing\RouteHandler::class, fn($object) => $object instanceof DependenciesTest\Routes3); $this->assertInstanceOf(DependenciesTest\Routes3::class, $routes3); $routes2 = $deps->resolve(DependenciesTest\Routes2::class); $this->assertInstanceOf(DependenciesTest\Routes2::class, $routes2); $all = $deps->all(\Index\Http\Routing\RouteHandler::class); $this->assertEquals(3, count($all)); $this->assertInstanceOf(DependenciesTest\Routes1::class, $all[0]); $this->assertInstanceOf(DependenciesTest\Routes2::class, $all[1]); $this->assertInstanceOf(DependenciesTest\Routes3::class, $all[2]); $some = $deps->all(\Index\Http\Routing\RouteHandler::class, fn($object) => !($object instanceof DependenciesTest\Routes2)); $this->assertEquals(2, count($some)); $this->assertInstanceOf(DependenciesTest\Routes1::class, $some[0]); $this->assertInstanceOf(DependenciesTest\Routes3::class, $some[1]); } } } namespace DependenciesTest { interface DependencyTestInterface {} class RequiredParamTestClass { public function __construct(public DependencyTestInterface $test) {} } class NullableParamTestClass { public function __construct(public ?DependencyTestInterface $test) {} } class Routes1 implements \Index\Http\Routing\RouteHandler { use \Index\Http\Routing\RouteHandlerCommon; } class Routes2 implements \Index\Http\Routing\RouteHandler { use \Index\Http\Routing\RouteHandlerCommon; } class Routes3 implements \Index\Http\Routing\RouteHandler { use \Index\Http\Routing\RouteHandlerCommon; } }