ldc-arcadia-api/tests/Unit/Domain/Services/BrandResolverTest.php
Jérémy Munsch abe60df95f feat(event): implement BrandCreated event and listeners
- Added BrandCreated event to encapsulate brand creation details.
- Created LogBrandCreated listener to log brand creation events.
- Updated BrandResolver to dispatch BrandCreated event upon new brand creation.
- Introduced EventServiceProvider to register event listeners.
- Added unit tests for BrandCreated event and LogBrandCreated listener.
2026-08-21 09:45:06 +02:00

119 lines
4.3 KiB
PHP

<?php
declare(strict_types=1);
namespace Tests\Unit\Domain\Services;
use Domain\Events\BrandCreated;
use Domain\Exceptions\BrandNotFoundException;
use Domain\Models\Entities\Brand;
use Domain\Models\ValueObjects\Brand\ArcadiaBrand;
use Domain\Models\ValueObjects\Brand\ArcadiaId;
use Domain\Models\ValueObjects\Brand\BrandCode;
use Domain\Models\ValueObjects\Brand\BrandId;
use Domain\Models\ValueObjects\Brand\BrandName;
use Domain\Services\BrandCodeGenerator;
use Domain\Services\BrandResolver;
use Infra\Adapters\Directories\InMemoryArcadiaBrandDirectory;
use Infra\Adapters\Repositories\InMemoryBrandRepository;
use Ramsey\Uuid\Uuid;
use Shared\DDD\Event\DomainEventDispatcher;
use Shared\DDD\Event\Event;
covers(BrandResolver::class);
describe('BrandResolver Unit Tests', function (): void {
$arcadiaDirectory = new InMemoryArcadiaBrandDirectory();
$brandRepository = new InMemoryBrandRepository();
$codeGenerator = new BrandCodeGenerator();
beforeEach(function () use ($arcadiaDirectory, $brandRepository): void {
$arcadiaDirectory->clear();
$brandRepository->clear();
});
it('returns existing brand if already present in repository without dispatching event', function () use ($arcadiaDirectory, $brandRepository, $codeGenerator): void {
// GIVEN
$existing = Brand::hydrate(
id: new BrandId(Uuid::uuid7()),
name: new BrandName('Le Gaulois'),
code: new BrandCode('LGL01'),
arcadiaId: new ArcadiaId(1),
);
$brandRepository->add($existing);
$dispatcher = new class () implements DomainEventDispatcher
{
/** @var list<Event> */
public array $dispatched = [];
public function dispatch(Event $event): void
{
$this->dispatched[] = $event;
}
};
$resolver = new BrandResolver($arcadiaDirectory, $brandRepository, $codeGenerator, $dispatcher);
// WHEN
$resolved = $resolver->resolve(new ArcadiaId(1));
// THEN
expect($resolved)->toBe($existing)
->and($dispatcher->dispatched)->toBeEmpty();
});
it('generates, persists and dispatches BrandCreated event when brand is not in repository but in Arcadia directory', function () use ($arcadiaDirectory, $brandRepository, $codeGenerator): void {
// GIVEN
$arcadiaDirectory->add(new ArcadiaBrand(new ArcadiaId(2), new BrandName('Maître CoQ')));
$dispatcher = new class () implements DomainEventDispatcher
{
/** @var list<Event> */
public array $dispatched = [];
public function dispatch(Event $event): void
{
$this->dispatched[] = $event;
}
};
$resolver = new BrandResolver($arcadiaDirectory, $brandRepository, $codeGenerator, $dispatcher);
// WHEN
$resolved = $resolver->resolve(new ArcadiaId(2));
// THEN
expect($resolved->arcadiaId->value)->toBe(2)
->and($resolved->name->value)->toBe('Maître CoQ')
->and(str_starts_with($resolved->code->value, 'MCQ'))->toBeTrue();
expect($brandRepository->findByArcadiaId(new ArcadiaId(2)))->not->toBeNull();
expect($dispatcher->dispatched)->toHaveCount(1)
->and($dispatcher->dispatched[0])->toBeInstanceOf(BrandCreated::class);
/** @var BrandCreated $event */
$event = $dispatcher->dispatched[0];
expect($event->arcadiaId->value)->toBe(2)
->and($event->brandName->value)->toBe('Maître CoQ')
->and($event->brandCode->value)->toBe($resolved->code->value)
->and($event->brandId->value)->toBe($resolved->id->value);
});
it('throws BrandNotFoundException when resolving an unknown ArcadiaId', function () use ($arcadiaDirectory, $brandRepository, $codeGenerator): void {
// GIVEN
$dispatcher = new class () implements DomainEventDispatcher
{
public function dispatch(Event $event): void
{
}
};
$resolver = new BrandResolver($arcadiaDirectory, $brandRepository, $codeGenerator, $dispatcher);
// WHEN & THEN
expect(fn () => $resolver->resolve(new ArcadiaId(999)))
->toThrow(BrandNotFoundException::class, 'Arcadia brand with ID 999 not found.');
});
});