test(UsecaseBuilder): add unit tests for UsecaseBuilder functionality

This commit introduces unit tests for the UsecaseBuilder and UsecaseExecutionBuilder, ensuring proper behavior when building and executing use cases.
This commit is contained in:
Jérémy Munsch 2026-08-13 12:47:39 +02:00
parent ccba793b4c
commit cc7a629193
Signed by: forge-joniko
GPG key ID: D7EFE2F5CB6CC0E4

View file

@ -0,0 +1,144 @@
<?php
declare(strict_types=1);
namespace Tests\Unit\Shared\DDD\Usecase\Builder;
use LogicException;
use Shared\DDD\Usecase\Builder\UsecaseBuilder;
use Shared\DDD\Usecase\Builder\UsecaseExecutionBuilder;
use Shared\DDD\Usecase\Builder\UsecaseExecutor;
use Shared\DDD\Usecase\Input;
use Shared\DDD\Usecase\Output;
use Shared\DDD\Usecase\Presenter;
use Shared\DDD\Usecase\Usecase;
covers(
UsecaseBuilder::class,
UsecaseExecutionBuilder::class
);
describe('UsecaseBuilder Unit Tests', function (): void {
it('successfully builds and executes a use case using fluent syntax', function (): void {
// GIVEN
$inputMock = new class () implements Input
{
};
$outputMock = new class () implements Output
{
};
$viewResult = new \stdClass();
$viewResult->success = true;
$usecaseMock = new class ($outputMock) implements Usecase
{
public function __construct(private readonly Output $output)
{
}
public function execute(Input $input): Output
{
return $this->output;
}
};
$presenterMock = new class ($viewResult) implements Presenter
{
public function __construct(private readonly object $view)
{
}
public function present(Output $output): object
{
return $this->view;
}
};
$executorMock = new class ($viewResult) implements UsecaseExecutor
{
public function __construct(private readonly object $view)
{
}
public function execute(Usecase $usecase, Input $input, Presenter $presenter): object
{
$output = $usecase->execute($input);
return $presenter->present($output);
}
};
// WHEN
$result = UsecaseBuilder::using($executorMock)
->do($usecaseMock)
->from($inputMock)
->with($presenterMock)
->run();
// THEN
expect($result)->toBe($viewResult);
});
it('throws LogicException when setting input before usecase', function (): void {
// GIVEN
$executorMock = new class () implements UsecaseExecutor
{
public function execute(Usecase $usecase, Input $input, Presenter $presenter): object
{
return new \stdClass();
}
};
$inputMock = new class () implements Input
{
};
// WHEN & THEN
$builder = new UsecaseExecutionBuilder($executorMock);
expect(fn () => $builder->from($inputMock))
->toThrow(LogicException::class, 'Usecase must be set before input.');
});
it('throws LogicException when setting presenter before input or usecase', function (): void {
// GIVEN
$executorMock = new class () implements UsecaseExecutor
{
public function execute(Usecase $usecase, Input $input, Presenter $presenter): object
{
return new \stdClass();
}
};
$presenterMock = new class () implements Presenter
{
public function present(Output $output): object
{
return new \stdClass();
}
};
// WHEN & THEN
$builder = new UsecaseExecutionBuilder($executorMock);
expect(fn () => $builder->with($presenterMock))
->toThrow(LogicException::class, 'Usecase and input must be set before presenter.');
});
it('throws LogicException when running uncompleted builder', function (): void {
// GIVEN
$executorMock = new class () implements UsecaseExecutor
{
public function execute(Usecase $usecase, Input $input, Presenter $presenter): object
{
return new \stdClass();
}
};
// WHEN & THEN
$builder = new UsecaseExecutionBuilder($executorMock);
expect(fn () => $builder->run())
->toThrow(LogicException::class, 'Usecase, input and presenter are all required.');
});
});