210 lines
No EOL
6.6 KiB
PHP
210 lines
No EOL
6.6 KiB
PHP
<?php
|
|
|
|
declare(strict_types = 1);
|
|
|
|
namespace Foundation\Tests\Unit\Core\DependencyInjection;
|
|
|
|
use DI\Container;
|
|
use Foundation\Core\DependencyInjection\AttributeProcessorInterface;
|
|
use Foundation\Core\DependencyInjection\InflectableContainer;
|
|
use PHPUnit\Framework\TestCase;
|
|
|
|
class InflectableContainerTest extends TestCase
|
|
{
|
|
private Container $phpDiContainer;
|
|
private InflectableContainer $container;
|
|
|
|
protected function setUp(): void {
|
|
$this->phpDiContainer = new Container();
|
|
$this->container = new InflectableContainer($this->phpDiContainer);
|
|
}
|
|
|
|
public function testCanGetAndSetServices(): void {
|
|
$this->container->set('test.value', 'hello world');
|
|
|
|
self::assertTrue($this->container->has('test.value'));
|
|
self::assertSame('hello world', $this->container->get('test.value'));
|
|
}
|
|
|
|
public function testCanMakeInstancesWithParameters(): void {
|
|
$instance = $this->container->make(TestClass::class, ['value' => 'test']);
|
|
|
|
self::assertInstanceOf(TestClass::class, $instance);
|
|
self::assertSame('test', $instance->getValue());
|
|
}
|
|
|
|
public function testCanRegisterClassWithoutDependencies(): void {
|
|
$instance = $this->container->register(TestClass::class);
|
|
|
|
self::assertInstanceOf(TestClass::class, $instance);
|
|
self::assertTrue($this->container->has(TestClass::class));
|
|
}
|
|
|
|
public function testCanRegisterClassWithDependencies(): void {
|
|
$this->container->set('dependency', new TestDependency('injected'));
|
|
|
|
$instance = $this->container->register(TestClassWithDependency::class, ['dependency']);
|
|
|
|
self::assertInstanceOf(TestClassWithDependency::class, $instance);
|
|
self::assertSame('injected', $instance->getDependencyValue());
|
|
}
|
|
|
|
public function testCanBindInterfaceToImplementation(): void {
|
|
$instance = $this->container->bind(TestInterface::class, TestImplementation::class);
|
|
|
|
self::assertInstanceOf(TestImplementation::class, $instance);
|
|
self::assertTrue($this->container->has(TestInterface::class));
|
|
|
|
$retrieved = $this->container->get(TestInterface::class);
|
|
self::assertInstanceOf(TestImplementation::class, $retrieved);
|
|
}
|
|
|
|
public function testCanBindInterfaceToImplementationWithDependencies(): void {
|
|
$this->container->set('dependency', new TestDependency('bound'));
|
|
|
|
$instance = $this->container->bind(
|
|
TestInterface::class,
|
|
TestImplementationWithDependency::class,
|
|
['dependency'],
|
|
);
|
|
|
|
self::assertInstanceOf(TestImplementationWithDependency::class, $instance);
|
|
self::assertSame('bound', $instance->getDependencyValue());
|
|
}
|
|
|
|
public function testInflectionSystemAppliesDirectClassInflections(): void {
|
|
$this->container->registerInflection(
|
|
TestInflectionTarget::class,
|
|
'setInjectedValue',
|
|
['injected_value'],
|
|
);
|
|
|
|
$instance = $this->container->make(TestInflectionTarget::class);
|
|
|
|
self::assertSame('injected_value', $instance->getInjectedValue());
|
|
}
|
|
|
|
public function testInflectionSystemAppliesInterfaceInflections(): void {
|
|
$this->container->registerInflection(
|
|
TestInflectionInterface::class,
|
|
'setInjectedValue',
|
|
['interface_value'],
|
|
);
|
|
|
|
$instance = $this->container->make(TestInflectionImplementation::class);
|
|
|
|
self::assertSame('interface_value', $instance->getInjectedValue());
|
|
}
|
|
|
|
public function testInflectionSystemResolvesParametersFromContainer(): void {
|
|
$dependency = new TestDependency('resolved');
|
|
$this->container->set(TestDependency::class, $dependency);
|
|
|
|
$this->container->registerInflection(
|
|
TestInflectionTarget::class,
|
|
'setDependency',
|
|
[TestDependency::class],
|
|
);
|
|
|
|
$instance = $this->container->make(TestInflectionTarget::class);
|
|
|
|
self::assertSame($dependency, $instance->getDependency());
|
|
}
|
|
|
|
public function testAttributeProcessorsAreCalledDuringRegistration(): void {
|
|
$processor = $this->createMock(AttributeProcessorInterface::class);
|
|
$processor->expects(self::once())->method('canProcess')->with(TestClass::class)->willReturn(true);
|
|
$processor->expects(self::once())->method('process')->with(TestClass::class);
|
|
|
|
$this->container->addAttributeProcessor($processor);
|
|
$this->container->register(TestClass::class);
|
|
}
|
|
|
|
public function testReturnsNonObjectsDirectly(): void {
|
|
$this->container->set('array.value', ['test' => 'array']);
|
|
$this->container->set('string.value', 'test string');
|
|
|
|
self::assertSame(['test' => 'array'], $this->container->get('array.value'));
|
|
self::assertSame('test string', $this->container->get('string.value'));
|
|
}
|
|
}
|
|
|
|
class TestClass
|
|
{
|
|
public function __construct(private readonly string $value = 'default') {}
|
|
|
|
public function getValue(): string {
|
|
return $this->value;
|
|
}
|
|
}
|
|
|
|
class TestDependency
|
|
{
|
|
public function __construct(private readonly string $value) {}
|
|
|
|
public function getValue(): string {
|
|
return $this->value;
|
|
}
|
|
}
|
|
|
|
class TestClassWithDependency
|
|
{
|
|
public function __construct(private readonly TestDependency $dependency) {}
|
|
|
|
public function getDependencyValue(): string {
|
|
return $this->dependency->getValue();
|
|
}
|
|
}
|
|
|
|
interface TestInterface { }
|
|
|
|
class TestImplementation implements TestInterface { }
|
|
|
|
class TestImplementationWithDependency implements TestInterface
|
|
{
|
|
public function __construct(private readonly TestDependency $dependency) {}
|
|
|
|
public function getDependencyValue(): string {
|
|
return $this->dependency->getValue();
|
|
}
|
|
}
|
|
|
|
interface TestInflectionInterface
|
|
{
|
|
public function setInjectedValue(string $value): void;
|
|
}
|
|
|
|
class TestInflectionTarget
|
|
{
|
|
private ?string $injectedValue = null;
|
|
private ?TestDependency $dependency = null;
|
|
|
|
public function setInjectedValue(string $value): void {
|
|
$this->injectedValue = $value;
|
|
}
|
|
|
|
public function getInjectedValue(): ?string {
|
|
return $this->injectedValue;
|
|
}
|
|
|
|
public function setDependency(TestDependency $dependency): void {
|
|
$this->dependency = $dependency;
|
|
}
|
|
|
|
public function getDependency(): ?TestDependency {
|
|
return $this->dependency;
|
|
}
|
|
}
|
|
|
|
class TestInflectionImplementation implements TestInflectionInterface
|
|
{
|
|
private ?string $injectedValue = null;
|
|
|
|
public function setInjectedValue(string $value): void {
|
|
$this->injectedValue = $value;
|
|
}
|
|
|
|
public function getInjectedValue(): ?string {
|
|
return $this->injectedValue;
|
|
}
|
|
} |