diff --git a/src/Tempest/CommandBus/src/CommandBusConfig.php b/src/Tempest/CommandBus/src/CommandBusConfig.php index f0715c0fa..a678cee48 100644 --- a/src/Tempest/CommandBus/src/CommandBusConfig.php +++ b/src/Tempest/CommandBus/src/CommandBusConfig.php @@ -17,8 +17,15 @@ public function __construct( ) { } + /** + * @throws CommandHandlerAlreadyExists + */ public function addHandler(CommandHandler $commandHandler, string $commandName, MethodReflector $handler): self { + if (array_key_exists($commandName, $this->handlers)) { + throw new CommandHandlerAlreadyExists($commandName, new: $handler, existing: $this->handlers[$commandName]->handler); + } + $this->handlers[$commandName] = $commandHandler ->setCommandName($commandName) ->setHandler($handler); diff --git a/src/Tempest/CommandBus/src/CommandHandlerAlreadyExists.php b/src/Tempest/CommandBus/src/CommandHandlerAlreadyExists.php new file mode 100644 index 000000000..b2d5f8902 --- /dev/null +++ b/src/Tempest/CommandBus/src/CommandHandlerAlreadyExists.php @@ -0,0 +1,16 @@ +getShortName()}, {$existing->getShortName()} already handles {$commandName}."); + } +} diff --git a/src/Tempest/CommandBus/tests/Fixtures/CreateUserCommandHandler.php b/src/Tempest/CommandBus/tests/Fixtures/CreateUserCommandHandler.php index 0757b6d8c..621336090 100644 --- a/src/Tempest/CommandBus/tests/Fixtures/CreateUserCommandHandler.php +++ b/src/Tempest/CommandBus/tests/Fixtures/CreateUserCommandHandler.php @@ -18,4 +18,10 @@ public function __invoke(CreateUserCommand $command): void $this->firstName = $command->firstName; $this->lastName = $command->lastName; } + + #[CommandHandler] + public function double(CreateUserCommand $command): void + { + // throws a CommandHandlerAlreadyExists exception since the command is already being handled by the __invoke method + } } diff --git a/src/Tempest/CommandBus/tests/GenericCommandBusTest.php b/src/Tempest/CommandBus/tests/GenericCommandBusTest.php index 2e929d574..edcabe8df 100644 --- a/src/Tempest/CommandBus/tests/GenericCommandBusTest.php +++ b/src/Tempest/CommandBus/tests/GenericCommandBusTest.php @@ -8,6 +8,7 @@ use Tempest\CommandBus\CommandBus; use Tempest\CommandBus\CommandBusConfig; use Tempest\CommandBus\CommandHandler; +use Tempest\CommandBus\CommandHandlerAlreadyExists; use Tempest\CommandBus\CommandHandlerNotFound; use Tempest\CommandBus\GenericCommandBus; use Tempest\CommandBus\Tests\Fixtures\CreateUserCommand; @@ -21,6 +22,8 @@ */ final class GenericCommandBusTest extends TestCase { + private CommandBusConfig $config; + private CommandBus $commandBus; public function test_getting_command_handler_that_exists(): void @@ -44,26 +47,41 @@ public function test_exception_is_thrown_when_command_handler_doesnt_exist(): vo $this->commandBus->dispatch($command); } + public function test_exception_is_thrown_when_command_handler_already_exist(): void + { + $createUserCommandHandlerClass = new ClassReflector(CreateUserCommandHandler::class); + $createUserCommandHandlerMethod = $createUserCommandHandlerClass->getMethod('__invoke'); + $createUserCommandHandler = $createUserCommandHandlerMethod->getAttribute(CommandHandler::class); + + $this->expectException(CommandHandlerAlreadyExists::class); + + $this->config->addHandler( + commandHandler: $createUserCommandHandler, + commandName: CreateUserCommand::class, + handler: $createUserCommandHandlerClass->getMethod('double'), + ); + } + protected function setUp(): void { parent::setUp(); // TODO: I'd like to make this easier to setup. - $config = new CommandBusConfig(); + $this->config = new CommandBusConfig(); $createUserCommandHandlerClass = new ClassReflector(CreateUserCommandHandler::class); $createUserCommandHandlerMethod = $createUserCommandHandlerClass->getMethod('__invoke'); $createUserCommandHandler = $createUserCommandHandlerMethod->getAttribute(CommandHandler::class); - $config->addHandler( + $this->config->addHandler( commandHandler: $createUserCommandHandler, commandName: CreateUserCommand::class, - handler: $createUserCommandHandlerMethod + handler: $createUserCommandHandlerMethod, ); $this->commandBus = new GenericCommandBus( container: new GenericContainer(), - commandBusConfig: $config + commandBusConfig: $this->config, ); } }