- 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.
118 lines
3.8 KiB
PHP
118 lines
3.8 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace Tests\Unit\Framework\DI\Attributes;
|
|
|
|
use App\Framework\Core\ValueObjects\ClassName;
|
|
use App\Framework\DI\Attributes\EnvAttributeResolver;
|
|
use App\Framework\DI\Attributes\LogChannelAttributeResolver;
|
|
use App\Framework\DI\Attributes\ParameterAttributeResolverInterface;
|
|
use App\Framework\DI\Attributes\ParameterAttributeResolverRegistry;
|
|
use App\Framework\DI\Container;
|
|
use App\Framework\Logging\Attributes\LogChannel as LogChannelAttribute;
|
|
use App\Framework\Logging\Logger;
|
|
use App\Framework\Logging\LogChannel;
|
|
|
|
// Test class
|
|
final class ServiceWithLogChannel
|
|
{
|
|
public function __construct(
|
|
#[LogChannelAttribute(LogChannel::CACHE)]
|
|
public Logger $logger
|
|
) {
|
|
}
|
|
}
|
|
|
|
// Mock Resolver für Tests
|
|
final class MockAttributeResolver implements ParameterAttributeResolverInterface
|
|
{
|
|
public function __construct(
|
|
private bool $shouldSupport,
|
|
private mixed $resolveValue
|
|
) {
|
|
}
|
|
|
|
public function supports(\ReflectionAttribute $attribute): bool
|
|
{
|
|
return $this->shouldSupport;
|
|
}
|
|
|
|
public function resolve(
|
|
\ReflectionParameter $param,
|
|
ClassName $className,
|
|
string $methodName
|
|
): mixed {
|
|
return $this->resolveValue;
|
|
}
|
|
}
|
|
|
|
beforeEach(function () {
|
|
$this->container = $this->createMock(Container::class);
|
|
});
|
|
|
|
describe('ParameterAttributeResolverRegistry', function () {
|
|
it('creates registry with variadic constructor', function () {
|
|
$resolver1 = new MockAttributeResolver(true, 'value1');
|
|
$resolver2 = new MockAttributeResolver(true, 'value2');
|
|
|
|
$registry = new ParameterAttributeResolverRegistry($resolver1, $resolver2);
|
|
|
|
expect($registry)->toBeInstanceOf(ParameterAttributeResolverRegistry::class);
|
|
});
|
|
|
|
it('creates empty registry', function () {
|
|
$registry = new ParameterAttributeResolverRegistry();
|
|
|
|
expect($registry)->toBeInstanceOf(ParameterAttributeResolverRegistry::class);
|
|
});
|
|
|
|
it('uses first resolver that supports attribute', function () {
|
|
$resolver1 = new MockAttributeResolver(false, 'value1');
|
|
$resolver2 = new MockAttributeResolver(true, 'value2');
|
|
$resolver3 = new MockAttributeResolver(true, 'value3');
|
|
|
|
$registry = new ParameterAttributeResolverRegistry($resolver1, $resolver2, $resolver3);
|
|
|
|
$reflectionParam = new \ReflectionParameter(
|
|
[ServiceWithLogChannel::class, '__construct'],
|
|
0
|
|
);
|
|
$attribute = $reflectionParam->getAttributes()[0] ?? null;
|
|
|
|
if ($attribute) {
|
|
$className = ClassName::create(ServiceWithLogChannel::class);
|
|
$result = $registry->resolve($reflectionParam, $className, '__construct');
|
|
|
|
// Der zweite Resolver sollte verwendet werden (erste der supports = true)
|
|
expect($result)->toBe('value2');
|
|
}
|
|
});
|
|
|
|
it('returns null when no resolver supports attribute', function () {
|
|
$resolver1 = new MockAttributeResolver(false, 'value1');
|
|
$resolver2 = new MockAttributeResolver(false, 'value2');
|
|
|
|
$registry = new ParameterAttributeResolverRegistry($resolver1, $resolver2);
|
|
|
|
$reflectionParam = new \ReflectionParameter(
|
|
[ServiceWithLogChannel::class, '__construct'],
|
|
0
|
|
);
|
|
$className = ClassName::create(ServiceWithLogChannel::class);
|
|
$result = $registry->resolve($reflectionParam, $className, '__construct');
|
|
|
|
expect($result)->toBeNull();
|
|
});
|
|
|
|
it('works with real resolvers', function () {
|
|
$logChannelResolver = new LogChannelAttributeResolver($this->container);
|
|
$envResolver = new EnvAttributeResolver($this->container);
|
|
|
|
$registry = new ParameterAttributeResolverRegistry($logChannelResolver, $envResolver);
|
|
|
|
expect($registry)->toBeInstanceOf(ParameterAttributeResolverRegistry::class);
|
|
});
|
|
});
|
|
|