1<?php declare(strict_types=1); 2 3namespace App\Tests\Unit\Container; 4 5use App\Container\Container; 6use App\Container\Exception\ContainerException; 7use App\Container\Exception\EntryNotFoundException; 8use PHPUnit\Framework\TestCase; 9 10class ContainerTest extends TestCase 11{ 12 public function testContainer(): void 13 { 14 // Create container 15 $container = new Container(); 16 17 // Service definitions 18 $container->set(MockService::class, function (Container $container) { 19 $service = new MockService($container->get(MockDependency::class)); 20 $service->setProperty('group.param'); 21 22 return $service; 23 }); 24 25 $container->set(MockDependency::class, function (Container $container) { 26 return new MockDependency('group.param'); 27 }); 28 29 // Check retrieval of service 30 $service = $container->get(MockService::class); 31 $this->assertInstanceOf(MockService::class, $service); 32 33 // Check retrieval of dependency 34 $dependency = $container->get(MockDependency::class); 35 $this->assertInstanceOf(MockDependency::class, $dependency); 36 37 // Check that the dependency has been reused 38 $this->assertSame($dependency, $service->getDependency()); 39 40 // Check the service calls have initialized 41 $this->assertEquals('group.param', $service->getProperty()); 42 } 43 44 public function testHas(): void 45 { 46 $container = new Container(); 47 48 $this->assertFalse($container->has(MockDependency::class)); 49 50 $container->set(MockDependency::class, function (Container $container) { 51 return new MockDependency('group.param'); 52 }); 53 54 $this->assertFalse($container->has(MockService::class)); 55 $this->assertTrue($container->has(MockDependency::class)); 56 } 57 58 public function testServiceNotFound(): void 59 { 60 $container = new Container(); 61 62 $this->expectException(EntryNotFoundException::class); 63 64 $container->get('foo'); 65 } 66 67 public function testBadServiceEntry(): void 68 { 69 $container = new Container(); 70 $container->set(\stdClass::class, ''); 71 72 $this->expectException(ContainerException::class); 73 $this->expectExceptionMessage('entry must be callable'); 74 75 $container->get(\stdClass::class); 76 } 77 78 public function testCircularReference(): void 79 { 80 $container = new Container(); 81 82 $container->set(MockService::class, function (Container $container) { 83 return new MockService($container->get(MockService::class)); 84 }); 85 86 $container->set(MockService::class, function (Container $container) { 87 return new MockService($container->get(MockService::class)); 88 }); 89 90 $this->expectException(ContainerException::class); 91 $this->expectExceptionMessage('circular reference'); 92 93 $container->get(MockService::class); 94 } 95 96 public function testParametersAndServices(): void 97 { 98 $container = new Container([ 99 'foo' => 'bar', 100 'baz' => function (Container $container) { 101 return $container->get('foo'); 102 }, 103 ]); 104 105 $this->assertTrue($container->has('foo')); 106 $this->assertTrue($container->has('baz')); 107 $this->assertEquals('bar', $container->get('foo')); 108 $this->assertEquals('bar', $container->get('baz')); 109 } 110} 111