<?php
namespace Uid\Utils\Container;
use PHPUnit\Framework\TestCase;
use Psr\Container\ContainerInterface AS PsrContainerInterface;
class ContainerTest extends TestCase
{
public function testConstruct()
{
$container = new Container(['bar' => ['value' => 'foo']]);
$this->assertEquals('foo', $container->get('bar'));
$this->assertSame($container, $container->get(Container::class));
$this->assertSame($container, $container->get(ContainerInterface::class));
$this->assertSame($container, $container->get(PsrContainerInterface::class));
}
public function testValue()
{
$container = (new Container())->value('value', 'VALUE');
$this->assertEquals('VALUE', $container->get('value'));
}
public function testAlias()
{
$container = (new Container())
->value('value', 'VALUE')
->alias('alias1', 'value')
->alias('alias2', 'value');
$this->assertEquals('VALUE', $container->get('alias1'));
$this->assertEquals('VALUE', $container->get('alias2'));
}
public function testCreate()
{
$container = (new Container())->create(ContainerTest::class);
$this->assertInstanceOf(ContainerTest::class, $container->get(ContainerTest::class));
}
public function testSet()
{
$container = (new Container())->set('Service', ContainerTest::class);
$this->assertInstanceOf(ContainerTest::class, $container->get('Service'));
}
public function testFactory()
{
$container = (new Container())
->factory(ContainerTest::class, fn() => new ContainerTest(), [], true)
->factory('Service1', fn(ContainerInterface $container) => $container->get(ContainerTest::class))
->factory('Service2', fn(ContainerTest $class) => $class)
->factory('Service3', fn(Container $class) => $class);
$this->assertInstanceOf(ContainerTest::class, $container->get(ContainerTest::class));
$this->assertInstanceOf(ContainerTest::class, $container->get('Service1'));
$this->assertInstanceOf(ContainerTest::class, $container->get('Service2'));
$this->assertInstanceOf(Container::class, $container->get('Service3'));
}
public function testSingleton()
{
$container = (new Container())
->factory(
'foo',
function() {
static $count = 0;
return ++$count;
},
[],
true
);
$this->assertEquals(1, $container->get('foo'));
$this->assertEquals(1, $container->get('foo'));
$this->assertSame($container->get('foo'), $container->get('foo'));
}
public function testGetThrowCorrectException()
{
$this->expectException(\Psr\Container\ContainerExceptionInterface::class);
$container = (new Container())->set('foo', function() {
throw new \RuntimeException();
});
$container->get('foo');
}
public function testNotFound()
{
$this->expectException(NotFoundException::class);
$container = new Container();
$container->get('nonexistent');
}
public function testInvoke()
{
$container = (new Container())
->factory('foo', fn() => new class() {
function getValue(ContainerInterface $c) { return 'Hello '. get_class($c); }
});
$result = $container->invoke('foo', 'getValue');
$this->assertEquals('Hello '.Container::class, $result);
}
public function testInvokeMethodNotFound()
{
$this->expectException(NotFoundException::class);
$container = new Container();
$container->invoke(Container::class, 'nonexistentMethod');
}
public function testInvokeMethodWithDependency()
{
$container = (new Container())->factory('foo', fn() => new class() {
function concat(ContainerTest $bar, $data, $end = '!')
{
return "Hello {$data}, ". get_class($bar). $end;
}
});
$result = $container->invoke('foo', 'concat', ['data' => 'hire']);
$this->assertEquals('Hello hire, '.self::class.'!', $result);
}
public function testInvokeMethodWithNonObjectEntry()
{
$this->expectException(ContainerException::class);
$container = new Container();
$container->invoke('nonexistent', 'someMethod');
}
}