Skip to content

Commit

Permalink
Allow multiple messages to be returned on converters (#21)
Browse files Browse the repository at this point in the history
* Allow multiple messages to be returned on converters

* Add testing and improve logic

* Add testing and improve logic

* Add testing and improve logic

* Add some tests and fix logic

Co-authored-by: jgmullor <[email protected]>
  • Loading branch information
jgmullor and jgmullor authored Jun 21, 2022
1 parent 42ca087 commit 1333eb1
Show file tree
Hide file tree
Showing 4 changed files with 254 additions and 3 deletions.
17 changes: 14 additions & 3 deletions src/Middleware/SimpleMessagePublisherMiddleware.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,23 @@ public function handle(Envelope $envelope, StackInterface $stack): Envelope
return $resultStack;
}

foreach ($commandsResult as $theCommand) {
if (null === $theCommand) {
foreach ($commandsResult as $commands) {
if (null === $commands) {
continue;
}

$this->messageBroker->dispatch($theCommand);
// We can accept both one or an array of commands to be dispatched
if (false === \is_array($commands)) {
$commands = [$commands];
}

foreach ($commands as $theCommand) {
if (false === \is_object($theCommand)) {
continue;
}

$this->messageBroker->dispatch($theCommand);
}
}

return $resultStack;
Expand Down
93 changes: 93 additions & 0 deletions tests/Bus/AllHandledStampExtractorTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
<?php
declare(strict_types=1);

namespace PcComponentes\SymfonyMessengerBundle\Tests\Bus;

use PcComponentes\Ddd\Domain\Model\ValueObject\Uuid;
use PcComponentes\Ddd\Util\Message\Serialization\JsonApi\SimpleMessageJsonApiSerializable;
use PcComponentes\Ddd\Util\Message\Serialization\JsonApi\SimpleMessageStreamDeserializer;
use PcComponentes\Ddd\Util\Message\Serialization\MessageMappingRegistry;
use PcComponentes\DddLogging\DomainTrace\Tracker;
use PcComponentes\SymfonyMessengerBundle\Bus\AllHandledStampExtractor;
use PcComponentes\SymfonyMessengerBundle\Middleware\SimpleMessagePublisherMiddleware;
use PcComponentes\SymfonyMessengerBundle\Serializer\SimpleMessageSerializer;
use PcComponentes\SymfonyMessengerBundle\Tests\Mock\CommandMock;
use PHPUnit\Framework\TestCase;
use Ramsey\Uuid\Uuid as RamseyUuid;
use Symfony\Component\Messenger\Envelope;
use Symfony\Component\Messenger\MessageBusInterface;
use Symfony\Component\Messenger\Middleware\StackMiddleware;
use Symfony\Component\Messenger\Stamp\HandledStamp;
use Symfony\Component\Messenger\Stamp\RedeliveryStamp;

final class AllHandledStampExtractorTest extends TestCase
{
private AllHandledStampExtractor $extractor;

public function setUp(): void
{
$this->extractor = new AllHandledStampExtractor();

parent::setUp();
}

public function test_given_single_command_is_returned_then_on()
{
$envelope = new Envelope(new \stdClass());
$handledStamp = new HandledStamp(CommandMock::fromPayload(Uuid::v4(), []), 'handler');
$handledEnvelope = $envelope->with($handledStamp);

$results = $this->extractor->extract($handledEnvelope);

$this->assertCount(1, $results);
$this->assertInstanceOf(CommandMock::class, $results[0]);
}

public function test_given_single_command_and_null_are_returned_then_on()
{
$envelope = new Envelope(new \stdClass());
$handledEnvelope = $envelope->with(
new HandledStamp(CommandMock::fromPayload(Uuid::v4(), []), 'converterA'),
new HandledStamp(null, 'converterB')
);

$results = $this->extractor->extract($handledEnvelope);

$this->assertCount(2, $results);
$this->assertInstanceOf(CommandMock::class, $results[0]);
$this->assertNull($results[1]);
}

public function test_given_single_and_multiple_command_are_returned_then_ok()
{
$envelope = new Envelope(new \stdClass());
$firstCommandId = Uuid::v4();
$secondCommandId = Uuid::v4();
$thirdCommandId = Uuid::v4();

$firstConverterHandledStamp = new HandledStamp(
CommandMock::fromPayload($thirdCommandId, []),
'firstHandler'
);
$handledEnvelope = $envelope->with($firstConverterHandledStamp);

$secondConverterHandledStamp = new HandledStamp([
CommandMock::fromPayload($firstCommandId, []),
CommandMock::fromPayload($secondCommandId, []),
], 'secondHandler');
$handledEnvelope = $handledEnvelope->with($secondConverterHandledStamp);

$results = $this->extractor->extract($handledEnvelope);

$this->assertCount(2, $results);

$this->assertInstanceOf(CommandMock::class, $results[0]);
$this->assertEquals($thirdCommandId, $results[0]->messageId());

$this->assertIsArray($results[1]);
$this->assertInstanceOf(CommandMock::class, $results[1][0]);
$this->assertEquals($firstCommandId, $results[1][0]->messageId());
$this->assertInstanceOf(CommandMock::class, $results[1][1]);
$this->assertEquals($secondCommandId, $results[1][1]->messageId());
}
}
119 changes: 119 additions & 0 deletions tests/Middleware/SimpleMessagePublisherMiddlewareTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
<?php
declare(strict_types=1);

namespace PcComponentes\SymfonyMessengerBundle\Tests\Middleware;

use PcComponentes\Ddd\Domain\Model\ValueObject\DateTimeValueObject;
use PcComponentes\Ddd\Domain\Model\ValueObject\Uuid;
use PcComponentes\SymfonyMessengerBundle\Bus\AllHandledStampExtractor;
use PcComponentes\SymfonyMessengerBundle\Middleware\SimpleMessagePublisherMiddleware;
use PcComponentes\SymfonyMessengerBundle\Tests\Mock\CommandMock;
use PcComponentes\SymfonyMessengerBundle\Tests\Mock\EventMock;
use PcComponentes\SymfonyMessengerBundle\Tests\Mock\FakeBus;
use Symfony\Component\Messenger\Envelope;
use Symfony\Component\Messenger\MessageBusInterface;
use Symfony\Component\Messenger\Stamp\HandledStamp;
use Symfony\Component\Messenger\Test\Middleware\MiddlewareTestCase;

final class SimpleMessagePublisherMiddlewareTest extends MiddlewareTestCase
{
private MessageBusInterface $bus;
private AllHandledStampExtractor $extractor;

public function setUp(): void
{
$this->bus = new FakeBus();
$this->extractor = new AllHandledStampExtractor();

parent::setUp();
}

public function test_given_converters_dispatch_only_one_command_per_converter_then_ok()
{
$firstMessageId = Uuid::v4();
$secondMessageId = Uuid::v4();

$envelope = new Envelope(EventMock::fromPayload(Uuid::v4(), Uuid::v4(), DateTimeValueObject::now(), []));
$envelope = $envelope->with(
new HandledStamp(CommandMock::fromPayload($firstMessageId, []), 'ConverterA'),
new HandledStamp(CommandMock::fromPayload($secondMessageId, []), 'ConverterB'),
);

$middleware = new SimpleMessagePublisherMiddleware($this->bus, $this->extractor);
$middleware->handle($envelope, $this->getStackMock());

$this->assertCount(2, $this->bus->getMessages());
$this->assertEquals($firstMessageId, $this->bus->getMessages()[0]->getMessage()->messageId()->value());
$this->assertEquals($secondMessageId, $this->bus->getMessages()[1]->getMessage()->messageId()->value());
}

public function test_given_converters_dispatch_one_command_and_the_other_does_not_dispatch_anything_then_ok()
{
$firstMessageId = Uuid::v4();

$envelope = new Envelope(EventMock::fromPayload(Uuid::v4(), Uuid::v4(), DateTimeValueObject::now(), []));
$envelope = $envelope->with(
new HandledStamp(CommandMock::fromPayload($firstMessageId, []), 'ConverterA'),
new HandledStamp(null, 'ConverterB'),
);

$middleware = new SimpleMessagePublisherMiddleware($this->bus, $this->extractor);
$middleware->handle($envelope, $this->getStackMock());

$this->assertCount(1, $this->bus->getMessages());
$this->assertEquals($firstMessageId, $this->bus->getMessages()[0]->getMessage()->messageId()->value());
}

public function test_given_converters_dispatch_both_one_command_and_an_array_of_commands_then_ok()
{
$firstMessageId = Uuid::v4();
$secondMessageId = Uuid::v4();
$thirdMessageId = Uuid::v4();

$envelope = new Envelope(EventMock::fromPayload(Uuid::v4(), Uuid::v4(), DateTimeValueObject::now(), []));
$envelope = $envelope->with(
new HandledStamp(CommandMock::fromPayload($firstMessageId, []), 'ConverterA'),
new HandledStamp([
CommandMock::fromPayload($secondMessageId, []),
CommandMock::fromPayload($thirdMessageId, []),
],
'ConverterB'
),
);

$middleware = new SimpleMessagePublisherMiddleware($this->bus, $this->extractor);
$middleware->handle($envelope, $this->getStackMock());

$this->assertCount(3, $this->bus->getMessages());
$this->assertEquals($firstMessageId, $this->bus->getMessages()[0]->getMessage()->messageId()->value());
$this->assertEquals($secondMessageId, $this->bus->getMessages()[1]->getMessage()->messageId()->value());
$this->assertEquals($thirdMessageId, $this->bus->getMessages()[2]->getMessage()->messageId()->value());
}

public function test_given_converters_dispatch_both_one_command_and_an_array_of_commands_with_one_null_then_ok()
{
$firstMessageId = Uuid::v4();
$secondMessageId = Uuid::v4();
$thirdMessageId = Uuid::v4();

$envelope = new Envelope(EventMock::fromPayload(Uuid::v4(), Uuid::v4(), DateTimeValueObject::now(), []));
$envelope = $envelope->with(
new HandledStamp(CommandMock::fromPayload($firstMessageId, []), 'ConverterA'),
new HandledStamp([
CommandMock::fromPayload($secondMessageId, []),
CommandMock::fromPayload($thirdMessageId, []),
null,
],
'ConverterB'
),
);

$middleware = new SimpleMessagePublisherMiddleware($this->bus, $this->extractor);
$middleware->handle($envelope, $this->getStackMock());

$this->assertCount(3, $this->bus->getMessages());
$this->assertEquals($firstMessageId, $this->bus->getMessages()[0]->getMessage()->messageId()->value());
$this->assertEquals($secondMessageId, $this->bus->getMessages()[1]->getMessage()->messageId()->value());
$this->assertEquals($thirdMessageId, $this->bus->getMessages()[2]->getMessage()->messageId()->value());
}
}
28 changes: 28 additions & 0 deletions tests/Mock/FakeBus.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?php declare(strict_types=1);

namespace PcComponentes\SymfonyMessengerBundle\Tests\Mock;

use Symfony\Component\Messenger\Envelope;
use Symfony\Component\Messenger\MessageBusInterface;

final class FakeBus implements MessageBusInterface
{
/** @var array<Envelope> */
private array $messages = [];

public function dispatch(object $message, array $stamps = []): Envelope
{
$envelope = Envelope::wrap($message, $stamps);
$this->messages[] = $envelope;

return $envelope;
}

/**
* @return array<Envelope>
*/
public function getMessages(): array
{
return $this->messages;
}
}

0 comments on commit 1333eb1

Please sign in to comment.