toString(); $brandId = new BrandId(Uuid::fromString($uuid)); $cacheData = [ 'id' => $uuid, 'name' => 'Le Gaulois', 'code' => 'LGL01', 'arcadiaId' => 1, ]; /** @var CacheInterface&Mockery\MockInterface $cacheMock */ $cacheMock = Mockery::mock(CacheInterface::class); $cacheMock->shouldReceive('get') ->once() ->with("brand:id:{$uuid}") ->andReturn($cacheData); $brandCache = new BrandCache($cacheMock); // WHEN $result = $brandCache->getById($brandId); // THEN expect($result)->not->toBeNull() ->and($result->id()->value)->toBe($brandId->value) ->and($result->name->value)->toBe('Le Gaulois') ->and($result->code->value)->toBe('LGL01') ->and($result->arcadiaId->value)->toBe(1); }); it('returns brand from cache when found by code', function (): void { // GIVEN $uuid = Uuid::uuid7()->toString(); $brandCode = new BrandCode('LGL01'); $cacheData = [ 'id' => $uuid, 'name' => 'Le Gaulois', 'code' => 'LGL01', 'arcadiaId' => 1, ]; /** @var CacheInterface&Mockery\MockInterface $cacheMock */ $cacheMock = Mockery::mock(CacheInterface::class); $cacheMock->shouldReceive('get') ->once() ->with('brand:code:LGL01') ->andReturn($cacheData); $brandCache = new BrandCache($cacheMock); // WHEN $result = $brandCache->getByCode($brandCode); // THEN expect($result)->not->toBeNull() ->and($result->code->value)->toBe('LGL01') ->and($result->name->value)->toBe('Le Gaulois'); }); it('returns brand from cache when found by arcadia id', function (): void { // GIVEN $uuid = Uuid::uuid7()->toString(); $arcadiaId = new ArcadiaId(10); $cacheData = [ 'id' => $uuid, 'name' => 'Maître CoQ', 'code' => 'MCQ01', 'arcadiaId' => 10, ]; /** @var CacheInterface&Mockery\MockInterface $cacheMock */ $cacheMock = Mockery::mock(CacheInterface::class); $cacheMock->shouldReceive('get') ->once() ->with('brand:arcadia:10') ->andReturn($cacheData); $brandCache = new BrandCache($cacheMock); // WHEN $result = $brandCache->getByArcadiaId($arcadiaId); // THEN expect($result)->not->toBeNull() ->and($result->arcadiaId->value)->toBe(10) ->and($result->name->value)->toBe('Maître CoQ'); }); it('returns null and recovers gracefully when cache data is corrupted', function (): void { // GIVEN $brandId = new BrandId(Uuid::uuid7()); /** @var CacheInterface&Mockery\MockInterface $cacheMock */ $cacheMock = Mockery::mock(CacheInterface::class); $cacheMock->shouldReceive('get') ->once() ->with("brand:id:{$brandId->value}") ->andReturn('corrupted_string'); $brandCache = new BrandCache($cacheMock); // WHEN $result = $brandCache->getById($brandId); // THEN expect($result)->toBeNull(); }); it('stores brand in cache across all key variations', function (): void { // GIVEN $uuid = Uuid::uuid7()->toString(); $brand = Brand::hydrate( id: new BrandId(Uuid::fromString($uuid)), name: new BrandName('Doux'), code: new BrandCode('DOX01'), arcadiaId: new ArcadiaId(20), ); $expectedData = [ 'id' => $uuid, 'name' => 'Doux', 'code' => 'DOX01', 'arcadiaId' => 20, ]; /** @var CacheInterface&Mockery\MockInterface $cacheMock */ $cacheMock = Mockery::mock(CacheInterface::class); $cacheMock->shouldReceive('set') ->once() ->with("brand:id:{$uuid}", $expectedData, 86400); $cacheMock->shouldReceive('set') ->once() ->with('brand:code:DOX01', $expectedData, 86400); $cacheMock->shouldReceive('set') ->once() ->with('brand:arcadia:20', $expectedData, 86400); $brandCache = new BrandCache($cacheMock); // WHEN $brandCache->put($brand); // THEN expect(true)->toBeTrue(); }); it('invalidates specific brand keys and collection key', function (): void { // GIVEN $uuid = Uuid::uuid7()->toString(); $brand = Brand::hydrate( id: new BrandId(Uuid::fromString($uuid)), name: new BrandName('Père Dodu'), code: new BrandCode('PRD01'), arcadiaId: new ArcadiaId(30), ); /** @var CacheInterface&Mockery\MockInterface $cacheMock */ $cacheMock = Mockery::mock(CacheInterface::class); $cacheMock->shouldReceive('delete') ->once() ->with('brand:all'); $cacheMock->shouldReceive('delete') ->once() ->with("brand:id:{$uuid}"); $cacheMock->shouldReceive('delete') ->once() ->with('brand:code:PRD01'); $cacheMock->shouldReceive('delete') ->once() ->with('brand:arcadia:30'); $brandCache = new BrandCache($cacheMock); // WHEN $brandCache->invalidate($brand); // THEN expect(true)->toBeTrue(); }); it('resets all brand caches when reset is called', function (): void { // GIVEN $uuid = Uuid::uuid7()->toString(); $cacheData = [ [ 'id' => $uuid, 'name' => 'Brand 1', 'code' => 'BRD01', 'arcadiaId' => 1, ], ]; /** @var CacheInterface&Mockery\MockInterface $cacheMock */ $cacheMock = Mockery::mock(CacheInterface::class); $cacheMock->shouldReceive('get') ->once() ->with('brand:all') ->andReturn($cacheData); $cacheMock->shouldReceive('delete') ->once() ->with('brand:all'); $cacheMock->shouldReceive('delete') ->once() ->with("brand:id:{$uuid}"); $cacheMock->shouldReceive('delete') ->once() ->with('brand:code:BRD01'); $cacheMock->shouldReceive('delete') ->once() ->with('brand:arcadia:1'); $brandCache = new BrandCache($cacheMock); // WHEN $brandCache->reset(); // THEN expect(true)->toBeTrue(); }); });