Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
133 changes: 133 additions & 0 deletions test/unit/Middleware/PostCommandHandlerMiddlewareTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
<?php

declare(strict_types=1);

namespace PhpCmd\CmdBusTest\Middleware;

use PhpCmd\CmdBus\Command\CommandResult;
use PhpCmd\CmdBus\Command\CommandStatus;
use PhpCmd\CmdBus\CommandHandlerInterface;
use PhpCmd\CmdBus\CommandInterface;
use PhpCmd\CmdBus\Middleware\PostCommandHandlerMiddleware;
use PhpCmd\CmdBus\MiddlewareInterface;
use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
use RuntimeException;
use stdClass;

#[CoversClass(PostCommandHandlerMiddleware::class)]
final class PostCommandHandlerMiddlewareTest extends TestCase
{
private PostCommandHandlerMiddleware $middleware;

/** @var CommandInterface&MockObject */
private CommandInterface $command;

/** @var CommandHandlerInterface&MockObject */
private CommandHandlerInterface $handler;

protected function setUp(): void
{
parent::setUp();

$this->middleware = new PostCommandHandlerMiddleware();
$this->command = $this->createMock(CommandInterface::class);
$this->handler = $this->createMock(CommandHandlerInterface::class);
}

public function testMiddlewareImplementsCorrectInterface(): void
{
$this->assertInstanceOf(MiddlewareInterface::class, $this->middleware);
}

public function testProcessWithCommandResultReturnsUnwrappedResult(): void
{
$expectedResult = 'unwrapped result';
$commandResult = new CommandResult(
$this->command,
CommandStatus::Success,
$expectedResult
);

// Handler should not be called when processing CommandResult
$this->handler->expects($this->never())
->method('handle');

$result = $this->middleware->process($commandResult, $this->handler);

$this->assertEquals($expectedResult, $result);
}

public function testProcessWithCommandResultReturnsResultForSuccessStatus(): void
{
$successResult = ['data' => 'success value'];
$commandResult = new CommandResult(
$this->command,
CommandStatus::Success,
$successResult
);

$result = $this->middleware->process($commandResult, $this->handler);

$this->assertEquals($successResult, $result);
}

public function testProcessWithCommandResultReturnsResultForFailureStatus(): void
{
$failureResult = new RuntimeException('Something went wrong');
$commandResult = new CommandResult(
$this->command,
CommandStatus::Failure,
$failureResult
);

$result = $this->middleware->process($commandResult, $this->handler);

$this->assertSame($failureResult, $result);
}

public function testProcessWithRegularCommandDelegatesToHandler(): void
{
$expectedResult = 'handler result';

$this->handler->expects($this->once())
->method('handle')
->with($this->identicalTo($this->command))
->willReturn($expectedResult);

$result = $this->middleware->process($this->command, $this->handler);

$this->assertEquals($expectedResult, $result);
}

public function testProcessWithRegularCommandPassesCommandCorrectly(): void
{
$this->handler->expects($this->once())
->method('handle')
->with($this->callback(function ($passedCommand) {
return $passedCommand === $this->command;
}))
->willReturn('test result');

$this->middleware->process($this->command, $this->handler);
}

public function testProcessCanHandleDifferentCommandResultTypes(): void
{
// Test with null result
$nullResult = new CommandResult($this->command, CommandStatus::Success, null);
$nullReturnValue = $this->middleware->process($nullResult, $this->handler);
$this->assertNull($nullReturnValue);

// Test with array result
$arrayResult = new CommandResult($this->command, CommandStatus::Success, ['key' => 'value']);
$arrayReturnValue = $this->middleware->process($arrayResult, $this->handler);
$this->assertEquals(['key' => 'value'], $arrayReturnValue);

// Test with object result
$objectResult = new CommandResult($this->command, CommandStatus::Success, new stdClass());
$objectReturnValue = $this->middleware->process($objectResult, $this->handler);
$this->assertInstanceOf(stdClass::class, $objectReturnValue);
}
}
131 changes: 131 additions & 0 deletions test/unit/Middleware/PreCommandHandlerMiddlewareTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
<?php

declare(strict_types=1);

namespace PhpCmd\CmdBusTest\Middleware;

use PhpCmd\CmdBus\CommandHandlerInterface;
use PhpCmd\CmdBus\CommandInterface;
use PhpCmd\CmdBus\Middleware\PreCommandHandlerMiddleware;
use PhpCmd\CmdBus\MiddlewareInterface;
use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
use stdClass;

#[CoversClass(PreCommandHandlerMiddleware::class)]
final class PreCommandHandlerMiddlewareTest extends TestCase
{
private PreCommandHandlerMiddleware $middleware;

/** @var CommandInterface&MockObject */
private CommandInterface $command;

/** @var CommandHandlerInterface&MockObject */
private CommandHandlerInterface $handler;

protected function setUp(): void
{
parent::setUp();

$this->middleware = new PreCommandHandlerMiddleware();
$this->command = $this->createMock(CommandInterface::class);
$this->handler = $this->createMock(CommandHandlerInterface::class);
}

public function testMiddlewareImplementsCorrectInterface(): void
{
$this->assertInstanceOf(MiddlewareInterface::class, $this->middleware);
}

public function testProcessDelegatesToHandler(): void
{
$expectedResult = 'handler result';

$this->handler->expects($this->once())
->method('handle')
->with($this->identicalTo($this->command))
->willReturn($expectedResult);

$result = $this->middleware->process($this->command, $this->handler);

$this->assertEquals($expectedResult, $result);
}

public function testProcessPassesCommandCorrectly(): void
{
$this->handler->expects($this->once())
->method('handle')
->with($this->callback(function ($passedCommand) {
return $passedCommand === $this->command;
}))
->willReturn('test result');

$this->middleware->process($this->command, $this->handler);
}

public function testProcessReturnsHandlerResult(): void
{
$handlerResults = [
'string result',
['array', 'result'],
42,
null,
new stdClass(),
];

foreach ($handlerResults as $expectedResult) {
$handler = $this->createMock(CommandHandlerInterface::class);
$handler->expects($this->once())
->method('handle')
->willReturn($expectedResult);

$result = $this->middleware->process($this->command, $handler);

$this->assertSame($expectedResult, $result);
}
}

public function testProcessCallsHandlerExactlyOnce(): void
{
$this->handler->expects($this->once())
->method('handle')
->willReturn('result');

$this->middleware->process($this->command, $this->handler);
}

public function testProcessWithDifferentCommands(): void
{
$command1 = $this->createMock(CommandInterface::class);
$command2 = $this->createMock(CommandInterface::class);

$this->handler->expects($this->exactly(2))
->method('handle')
->willReturnCallback(function ($command) use ($command1, $command2) {
if ($command === $command1) {
return 'result1';
}
if ($command === $command2) {
return 'result2';
}
return 'default';
});

$result1 = $this->middleware->process($command1, $this->handler);
$result2 = $this->middleware->process($command2, $this->handler);

$this->assertEquals('result1', $result1);
$this->assertEquals('result2', $result2);
}

public function testMiddlewareCanBeInstantiatedMultipleTimes(): void
{
$middleware1 = new PreCommandHandlerMiddleware();
$middleware2 = new PreCommandHandlerMiddleware();

$this->assertInstanceOf(PreCommandHandlerMiddleware::class, $middleware1);
$this->assertInstanceOf(PreCommandHandlerMiddleware::class, $middleware2);
$this->assertNotSame($middleware1, $middleware2);
}
}