feat(di): implement attribute resolver system for dependency injection
- Introduce `ParameterAttributeResolverInterface` for handling attribute-based parameter resolution. - Add `EnvAttributeResolver` to inject environment variables with type conversion. - Add `LogChannelAttributeResolver` to inject channel-specific loggers. - Create `ParameterAttributeResolverRegistry` to manage available resolvers. - Update `ParameterResolver` to delegate attribute resolution to the registry. - Add comprehensive unit tests for all attribute resolvers and registry functionality.
This commit is contained in:
@@ -0,0 +1,80 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Tests\Unit\Framework\DI\Attributes;
|
||||
|
||||
use App\Framework\Core\ValueObjects\ClassName;
|
||||
use App\Framework\DI\Attributes\LogChannelAttributeResolver;
|
||||
use App\Framework\DI\Container;
|
||||
use App\Framework\Logging\Attributes\LogChannel as LogChannelAttribute;
|
||||
use App\Framework\Logging\DefaultLogger;
|
||||
use App\Framework\Logging\HasChannel;
|
||||
use App\Framework\Logging\Logger;
|
||||
use App\Framework\Logging\LogChannel;
|
||||
use App\Framework\Logging\SupportsChannels;
|
||||
|
||||
// Test class
|
||||
final class ServiceWithLogChannel
|
||||
{
|
||||
public function __construct(
|
||||
#[LogChannelAttribute(LogChannel::CACHE)]
|
||||
public Logger $logger
|
||||
) {
|
||||
}
|
||||
}
|
||||
|
||||
beforeEach(function () {
|
||||
$this->container = $this->createMock(Container::class);
|
||||
$this->resolver = new LogChannelAttributeResolver($this->container);
|
||||
});
|
||||
|
||||
describe('LogChannelAttributeResolver', function () {
|
||||
it('supports LogChannel attribute', function () {
|
||||
$reflectionParam = new \ReflectionParameter(
|
||||
[ServiceWithLogChannel::class, '__construct'],
|
||||
0
|
||||
);
|
||||
$attributes = $reflectionParam->getAttributes(LogChannelAttribute::class);
|
||||
|
||||
expect($attributes)->not->toBeEmpty();
|
||||
expect($this->resolver->supports($attributes[0]))->toBeTrue();
|
||||
});
|
||||
|
||||
it('does not support other attributes', function () {
|
||||
$reflectionParam = new \ReflectionParameter(
|
||||
[ServiceWithLogChannel::class, '__construct'],
|
||||
0
|
||||
);
|
||||
$attributes = $reflectionParam->getAttributes();
|
||||
|
||||
// Prüfe, ob es ein anderes Attribut gibt (falls vorhanden)
|
||||
foreach ($attributes as $attr) {
|
||||
if ($attr->getName() !== LogChannelAttribute::class) {
|
||||
expect($this->resolver->supports($attr))->toBeFalse();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
it('resolves LogChannel attribute to channel logger', function () {
|
||||
$mainLogger = new DefaultLogger();
|
||||
|
||||
$this->container->expects($this->once())
|
||||
->method('get')
|
||||
->with(SupportsChannels::class)
|
||||
->willReturn($mainLogger);
|
||||
|
||||
$className = ClassName::create(ServiceWithLogChannel::class);
|
||||
$reflectionParam = new \ReflectionParameter(
|
||||
[ServiceWithLogChannel::class, '__construct'],
|
||||
0
|
||||
);
|
||||
|
||||
$result = $this->resolver->resolve($reflectionParam, $className, '__construct');
|
||||
|
||||
expect($result)->toBeInstanceOf(Logger::class);
|
||||
expect($result)->toBeInstanceOf(HasChannel::class);
|
||||
expect($result->channel)->toBe(LogChannel::CACHE);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user