Files
michaelschiemer/tests/Unit/Framework/Config/EnumResolverTest.php
Michael Schiemer a1242f776e refactor(config): add EnumResolver for cache-backed enum resolution and extend DockerSecretsResolver with caching
- Introduce `EnumResolver` to centralize and cache enum value conversions.
- Enhance `DockerSecretsResolver` with result caching to avoid redundant file reads and improve performance.
- Update `Environment` to integrate `EnumResolver` for enriched enum resolution support and improved maintainability.
- Adjust unit tests to validate caching mechanisms and error handling improvements.
2025-11-03 23:47:08 +01:00

147 lines
5.2 KiB
PHP

<?php
declare(strict_types=1);
use App\Framework\Config\EnumResolver;
use BackedEnum;
describe('EnumResolver', function () {
beforeEach(function () {
$this->resolver = new EnumResolver();
});
describe('resolve()', function () {
it('converts string value to enum', function () {
// Create a test enum
if (!enum_exists('TestEnum')) {
eval('enum TestEnum: string { case FOO = "foo"; case BAR = "bar"; }');
}
$default = TestEnum::BAR;
$result = $this->resolver->resolve('foo', TestEnum::class, $default);
expect($result)->toBe(TestEnum::FOO);
});
it('converts int value to enum', function () {
// Create a test enum with int backing
if (!enum_exists('IntTestEnum')) {
eval('enum IntTestEnum: int { case ONE = 1; case TWO = 2; }');
}
$default = IntTestEnum::TWO;
$result = $this->resolver->resolve(1, IntTestEnum::class, $default);
expect($result)->toBe(IntTestEnum::ONE);
});
it('returns default when value cannot be converted', function () {
if (!enum_exists('TestEnum')) {
eval('enum TestEnum: string { case FOO = "foo"; case BAR = "bar"; }');
}
$default = TestEnum::BAR;
$result = $this->resolver->resolve('invalid', TestEnum::class, $default);
expect($result)->toBe($default);
});
it('returns default when value is null', function () {
if (!enum_exists('TestEnum')) {
eval('enum TestEnum: string { case FOO = "foo"; case BAR = "bar"; }');
}
$default = TestEnum::BAR;
$result = $this->resolver->resolve(null, TestEnum::class, $default);
expect($result)->toBe($default);
});
it('throws exception when default is not instance of enum class', function () {
if (!enum_exists('TestEnum')) {
eval('enum TestEnum: string { case FOO = "foo"; case BAR = "bar"; }');
}
if (!enum_exists('AnotherEnum')) {
eval('enum AnotherEnum: string { case BAZ = "baz"; }');
}
$wrongDefault = AnotherEnum::BAZ;
expect(function () use ($wrongDefault) {
$this->resolver->resolve('foo', TestEnum::class, $wrongDefault);
})->toThrow(\InvalidArgumentException::class);
});
});
describe('caching', function () {
it('caches enum conversion results', function () {
if (!enum_exists('TestEnum')) {
eval('enum TestEnum: string { case FOO = "foo"; case BAR = "bar"; }');
}
$default = TestEnum::BAR;
// First call - should convert
$enum1 = $this->resolver->resolve('foo', TestEnum::class, $default);
expect($enum1)->toBe(TestEnum::FOO);
// Second call to same resolver instance should use cache
// (We can't directly verify cache, but we can verify it returns the same instance)
$enum2 = $this->resolver->resolve('foo', TestEnum::class, $default);
expect($enum2)->toBe(TestEnum::FOO);
expect($enum1)->toBe($enum2);
});
it('caches different enum classes separately', function () {
if (!enum_exists('TestEnum')) {
eval('enum TestEnum: string { case FOO = "foo"; case BAR = "bar"; }');
}
if (!enum_exists('AnotherTestEnum')) {
eval('enum AnotherTestEnum: string { case FOO = "foo"; case BAR = "bar"; }');
}
$default1 = TestEnum::BAR;
$default2 = AnotherTestEnum::BAR;
$enum1 = $this->resolver->resolve('foo', TestEnum::class, $default1);
$enum2 = $this->resolver->resolve('foo', AnotherTestEnum::class, $default2);
expect($enum1)->toBe(TestEnum::FOO);
expect($enum2)->toBe(AnotherTestEnum::FOO);
expect($enum1)->not->toBe($enum2); // Different enum classes
});
it('caches different values separately', function () {
if (!enum_exists('TestEnum')) {
eval('enum TestEnum: string { case FOO = "foo"; case BAR = "bar"; }');
}
$default = TestEnum::BAR;
$enum1 = $this->resolver->resolve('foo', TestEnum::class, $default);
$enum2 = $this->resolver->resolve('bar', TestEnum::class, $default);
expect($enum1)->toBe(TestEnum::FOO);
expect($enum2)->toBe(TestEnum::BAR);
});
it('caches default values', function () {
if (!enum_exists('TestEnum')) {
eval('enum TestEnum: string { case FOO = "foo"; case BAR = "bar"; }');
}
$default = TestEnum::BAR;
// First call with null
$enum1 = $this->resolver->resolve(null, TestEnum::class, $default);
expect($enum1)->toBe($default);
// Second call with null should return cached default
$enum2 = $this->resolver->resolve(null, TestEnum::class, $default);
expect($enum2)->toBe($default);
expect($enum1)->toBe($enum2);
});
});
});