Enable Discovery debug logging for production troubleshooting
- Add DISCOVERY_LOG_LEVEL=debug - Add DISCOVERY_SHOW_PROGRESS=true - Temporary changes for debugging InitializerProcessor fixes on production
This commit is contained in:
206
tests/Framework/CommandBus/DefaultCommandBusTest.php
Normal file
206
tests/Framework/CommandBus/DefaultCommandBusTest.php
Normal file
@@ -0,0 +1,206 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use App\Framework\CommandBus\CommandHandlerDescriptor;
|
||||
use App\Framework\CommandBus\CommandHandlersCollection;
|
||||
use App\Framework\CommandBus\DefaultCommandBus;
|
||||
use App\Framework\CommandBus\Exceptions\NoHandlerFound;
|
||||
use App\Framework\CommandBus\ShouldQueue;
|
||||
use App\Framework\Context\ContextType;
|
||||
use App\Framework\Context\ExecutionContext;
|
||||
use App\Framework\DI\DefaultContainer;
|
||||
use App\Framework\Logging\Logger;
|
||||
use App\Framework\Queue\Queue;
|
||||
|
||||
beforeEach(function () {
|
||||
$this->container = new DefaultContainer();
|
||||
$this->executionContext = createTestExecutionContext();
|
||||
$this->queue = new TestQueue();
|
||||
$this->logger = new TestLogger();
|
||||
});
|
||||
|
||||
test('command handlers collection returns correct handler', function () {
|
||||
$descriptor = new CommandHandlerDescriptor(TestCommandHandler::class, 'handle', TestCommand::class);
|
||||
$collection = new CommandHandlersCollection($descriptor);
|
||||
|
||||
$retrieved = $collection->get(TestCommand::class);
|
||||
|
||||
expect($retrieved)->toBe($descriptor)
|
||||
->and($retrieved->class)->toBe(TestCommandHandler::class)
|
||||
->and($retrieved->method)->toBe('handle')
|
||||
->and($retrieved->command)->toBe(TestCommand::class);
|
||||
});
|
||||
|
||||
test('command handlers collection returns null for non-existent command', function () {
|
||||
$collection = new CommandHandlersCollection();
|
||||
|
||||
$result = $collection->get('NonExistentCommand');
|
||||
|
||||
expect($result)->toBeNull();
|
||||
});
|
||||
|
||||
test('command handler descriptor stores class and method', function () {
|
||||
$descriptor = new CommandHandlerDescriptor('TestClass', 'testMethod', 'TestCommand');
|
||||
|
||||
expect($descriptor->class)->toBe('TestClass')
|
||||
->and($descriptor->method)->toBe('testMethod')
|
||||
->and($descriptor->command)->toBe('TestCommand');
|
||||
});
|
||||
|
||||
test('no handler found exception contains command class', function () {
|
||||
$commandClass = 'TestCommand';
|
||||
$exception = NoHandlerFound::forCommand($commandClass);
|
||||
|
||||
expect($exception->getMessage())
|
||||
->toContain($commandClass);
|
||||
});
|
||||
|
||||
test('dispatch executes command handler directly', function () {
|
||||
$command = new TestCommand('test-data');
|
||||
$handler = new TestCommandHandler();
|
||||
$handlerDescriptor = new CommandHandlerDescriptor(TestCommandHandler::class, 'handle', TestCommand::class);
|
||||
$commandHandlers = new CommandHandlersCollection($handlerDescriptor);
|
||||
|
||||
$commandBus = new DefaultCommandBus(
|
||||
$commandHandlers,
|
||||
$this->container,
|
||||
$this->executionContext,
|
||||
$this->queue,
|
||||
$this->logger,
|
||||
[] // No middlewares for basic tests
|
||||
);
|
||||
|
||||
$this->container->instance(TestCommandHandler::class, $handler);
|
||||
|
||||
$result = $commandBus->dispatch($command);
|
||||
|
||||
expect($result)->toBe('Handled: test-data');
|
||||
});
|
||||
|
||||
test('dispatch throws exception when no handler found', function () {
|
||||
$command = new TestCommand('test-data');
|
||||
$commandHandlers = new CommandHandlersCollection(); // Empty collection
|
||||
|
||||
$commandBus = new DefaultCommandBus(
|
||||
$commandHandlers,
|
||||
$this->container,
|
||||
$this->executionContext,
|
||||
$this->queue,
|
||||
$this->logger,
|
||||
[] // No middlewares for basic tests
|
||||
);
|
||||
|
||||
expect(fn () => $commandBus->dispatch($command))
|
||||
->toThrow(NoHandlerFound::class);
|
||||
});
|
||||
|
||||
test('should queue attribute is recognized', function () {
|
||||
$command = new QueueableTestCommand('queue-data');
|
||||
$commandHandlers = new CommandHandlersCollection(); // Empty collection to test queueing
|
||||
|
||||
$commandBus = new DefaultCommandBus(
|
||||
$commandHandlers,
|
||||
$this->container,
|
||||
$this->executionContext,
|
||||
$this->queue,
|
||||
$this->logger,
|
||||
[] // No middlewares for basic tests
|
||||
);
|
||||
|
||||
// For queued commands, the result should be null
|
||||
$result = $commandBus->dispatch($command);
|
||||
|
||||
expect($result)->toBeNull()
|
||||
->and($this->queue->wasUsed())->toBeTrue();
|
||||
});
|
||||
|
||||
// Test fixtures
|
||||
class TestCommand
|
||||
{
|
||||
public function __construct(
|
||||
public readonly string $data
|
||||
) {
|
||||
}
|
||||
}
|
||||
|
||||
#[ShouldQueue]
|
||||
class QueueableTestCommand
|
||||
{
|
||||
public function __construct(
|
||||
public readonly string $data
|
||||
) {
|
||||
}
|
||||
}
|
||||
|
||||
class TestCommandHandler
|
||||
{
|
||||
public function handle(TestCommand $command): string
|
||||
{
|
||||
return 'Handled: ' . $command->data;
|
||||
}
|
||||
}
|
||||
|
||||
// ExecutionContext is final, so we create a simple instance
|
||||
function createTestExecutionContext(): ExecutionContext
|
||||
{
|
||||
return new ExecutionContext(ContextType::WEB);
|
||||
}
|
||||
|
||||
class TestQueue implements Queue
|
||||
{
|
||||
private bool $used = false;
|
||||
|
||||
private array $jobs = [];
|
||||
|
||||
public function push(object $job): void
|
||||
{
|
||||
$this->used = true;
|
||||
$this->jobs[] = $job;
|
||||
}
|
||||
|
||||
public function pop(): ?object
|
||||
{
|
||||
return array_shift($this->jobs);
|
||||
}
|
||||
|
||||
public function wasUsed(): bool
|
||||
{
|
||||
return $this->used;
|
||||
}
|
||||
}
|
||||
|
||||
class TestLogger implements Logger
|
||||
{
|
||||
public function emergency(string $message, array $context = []): void
|
||||
{
|
||||
}
|
||||
|
||||
public function alert(string $message, array $context = []): void
|
||||
{
|
||||
}
|
||||
|
||||
public function critical(string $message, array $context = []): void
|
||||
{
|
||||
}
|
||||
|
||||
public function error(string $message, array $context = []): void
|
||||
{
|
||||
}
|
||||
|
||||
public function warning(string $message, array $context = []): void
|
||||
{
|
||||
}
|
||||
|
||||
public function notice(string $message, array $context = []): void
|
||||
{
|
||||
}
|
||||
|
||||
public function info(string $message, array $context = []): void
|
||||
{
|
||||
}
|
||||
|
||||
public function debug(string $message, array $context = []): void
|
||||
{
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user