diff --git a/Makefile b/Makefile index 119f260..b581a6a 100644 --- a/Makefile +++ b/Makefile @@ -8,7 +8,7 @@ debug: .PHONY: update-dependencies update-dependencies: - docker-compose run composer update + docker-compose run composer update --ignore-platform-req=ext-sockets .PHONY: checkstyle checkstyle: diff --git a/README.md b/README.md index fe686c5..c0ddc4b 100644 --- a/README.md +++ b/README.md @@ -121,12 +121,14 @@ class EventServiceProvider extends ServiceProvider ### Custom middlewares -The middlewares should implement the `Softonic\TransactionalEventPublisher\Contracts\EventStoreMiddlewareContract` interface. +The middlewares should implement the `Softonic\TransactionalEventPublisher\Interfaces\EventStoreMiddlewareInterface` interface. Its purpose is to store the domain event provided, so you can implement any storage for domain events. ### Custom messages -The `transactional-event.message` class must implement `EventMessageContract` and `transactional-event.middleware` class must implement `EventStoreMiddlewareContract`. +The `transactional-event.messageBuilder` class must implement `EventMessageBuilderInterface` and `transactional-event.middleware` class must implement `EventStoreMiddlewareInterface`. + +The builder should return a `EventMessageInterface` value object. It just needs to implement the `toArray` and `jsonSerialize` methods with all the attributes that you need. Considerations ============== diff --git a/config/transactional-event-publisher.php b/config/transactional-event-publisher.php index 5e38a33..4b2f430 100644 --- a/config/transactional-event-publisher.php +++ b/config/transactional-event-publisher.php @@ -1,8 +1,9 @@ EventMessage::class, + 'messageBuilder' => EventMessageBuilder::class, /* |-------------------------------------------------------------------------- diff --git a/database/factories/DomainEventFactory.php b/database/factories/DomainEventFactory.php index 29bf018..500781c 100644 --- a/database/factories/DomainEventFactory.php +++ b/database/factories/DomainEventFactory.php @@ -5,7 +5,6 @@ use Illuminate\Database\Eloquent\Factories\Factory; use Softonic\TransactionalEventPublisher\CustomEventMessage; use Softonic\TransactionalEventPublisher\Models\DomainEvent; -use Softonic\TransactionalEventPublisher\TestModel; class DomainEventFactory extends Factory { @@ -18,13 +17,11 @@ class DomainEventFactory extends Factory /** * Define the model's default state. - * - * @return array */ public function definition(): array { return [ - 'message' => new CustomEventMessage(new TestModel(), 'testEvent') + 'message' => new CustomEventMessage() ]; } } diff --git a/src/Builders/EventMessageBuilder.php b/src/Builders/EventMessageBuilder.php new file mode 100644 index 0000000..8b1fb73 --- /dev/null +++ b/src/Builders/EventMessageBuilder.php @@ -0,0 +1,27 @@ +toArray(), + createdAt: Carbon::now()->toDateTimeString(), + ); + } +} diff --git a/src/Console/Commands/EmitEvents.php b/src/Console/Commands/EmitEvents.php index 291a3ed..da567dc 100644 --- a/src/Console/Commands/EmitEvents.php +++ b/src/Console/Commands/EmitEvents.php @@ -11,7 +11,7 @@ use Illuminate\Support\LazyCollection; use InvalidArgumentException; use RuntimeException; -use Softonic\TransactionalEventPublisher\Contracts\EventStoreMiddlewareContract; +use Softonic\TransactionalEventPublisher\Interfaces\EventStoreMiddlewareInterface; use Softonic\TransactionalEventPublisher\Models\DomainEvent; class EmitEvents extends Command @@ -38,7 +38,7 @@ class EmitEvents extends Command protected $description = 'Continuously emits domain events in batches'; - public EventStoreMiddlewareContract $eventPublisherMiddleware; + public EventStoreMiddlewareInterface $eventPublisherMiddleware; public string $dbConnection; @@ -52,7 +52,7 @@ class EmitEvents extends Command private bool $eventsProcessed; - public function handle(EventStoreMiddlewareContract $eventPublisherMiddleware): void + public function handle(EventStoreMiddlewareInterface $eventPublisherMiddleware): void { $this->eventPublisherMiddleware = $eventPublisherMiddleware; diff --git a/src/Contracts/EventMessageContract.php b/src/Contracts/EventMessageContract.php deleted file mode 100644 index 29c3228..0000000 --- a/src/Contracts/EventMessageContract.php +++ /dev/null @@ -1,16 +0,0 @@ -service . '.' . $message->eventType . '.' . $message->modelName; if (isset($this->properties['routing_key_fields'])) { diff --git a/src/EventStoreMiddlewares/DatabaseMiddleware.php b/src/EventStoreMiddlewares/DatabaseMiddleware.php index 5879ba1..61f2bd0 100644 --- a/src/EventStoreMiddlewares/DatabaseMiddleware.php +++ b/src/EventStoreMiddlewares/DatabaseMiddleware.php @@ -4,16 +4,16 @@ use Exception; use Illuminate\Support\Facades\DB; -use Softonic\TransactionalEventPublisher\Contracts\EventMessageContract; -use Softonic\TransactionalEventPublisher\Contracts\EventStoreMiddlewareContract; +use Softonic\TransactionalEventPublisher\Interfaces\EventMessageInterface; +use Softonic\TransactionalEventPublisher\Interfaces\EventStoreMiddlewareInterface; use Softonic\TransactionalEventPublisher\Models\DomainEvent; -class DatabaseMiddleware implements EventStoreMiddlewareContract +class DatabaseMiddleware implements EventStoreMiddlewareInterface { /** * Stores the messages in database. */ - public function store(EventMessageContract ...$messages): bool + public function store(EventMessageInterface ...$messages): bool { try { $inserts = []; diff --git a/src/Factories/AmqpMessageFactory.php b/src/Factories/AmqpMessageFactory.php index da1da42..8e679ff 100644 --- a/src/Factories/AmqpMessageFactory.php +++ b/src/Factories/AmqpMessageFactory.php @@ -4,14 +4,14 @@ use LogicException; use PhpAmqpLib\Message\AMQPMessage; -use Softonic\TransactionalEventPublisher\Contracts\EventMessageContract; +use Softonic\TransactionalEventPublisher\Interfaces\EventMessageInterface; class AmqpMessageFactory { /** * Makes a AMQPMessage object. */ - public function make(EventMessageContract $eventMessage, array $properties = []): AMQPMessage + public function make(EventMessageInterface $eventMessage, array $properties = []): AMQPMessage { $this->checkMessage($eventMessage->toArray()); diff --git a/src/Interfaces/EventMessageBuilderInterface.php b/src/Interfaces/EventMessageBuilderInterface.php new file mode 100644 index 0000000..e429d5b --- /dev/null +++ b/src/Interfaces/EventMessageBuilderInterface.php @@ -0,0 +1,10 @@ +attributes['message'] = serialize(clone $message); } diff --git a/src/Observers/ModelObserver.php b/src/Observers/ModelObserver.php index 4fd2175..4d6ebbc 100644 --- a/src/Observers/ModelObserver.php +++ b/src/Observers/ModelObserver.php @@ -3,19 +3,23 @@ namespace Softonic\TransactionalEventPublisher\Observers; use Illuminate\Database\Eloquent\Model; -use Softonic\TransactionalEventPublisher\Contracts\EventStoreMiddlewareContract; use Softonic\TransactionalEventPublisher\Exceptions\EventStoreFailedException; +use Softonic\TransactionalEventPublisher\Interfaces\EventMessageBuilderInterface; +use Softonic\TransactionalEventPublisher\Interfaces\EventStoreMiddlewareInterface; class ModelObserver { - private $eventStoreMiddleware; + /** + * @var EventStoreMiddlewareInterface[] + */ + private array $eventStoreMiddleware; /** - * @param EventStoreMiddlewareContract | EventStoreMiddlewareContract[] $eventStoreMiddleware + * @param EventStoreMiddlewareInterface | EventStoreMiddlewareInterface[] $eventStoreMiddleware */ public function __construct( - $eventStoreMiddleware, - private readonly string $messageClass + array|EventStoreMiddlewareInterface $eventStoreMiddleware, + protected readonly EventMessageBuilderInterface $builder ) { $this->eventStoreMiddleware = is_array($eventStoreMiddleware) ? $eventStoreMiddleware : [$eventStoreMiddleware]; } @@ -77,7 +81,7 @@ public function deleted(Model $model): bool private function performStoreEventMessage(Model $model, $modelEvent): void { $connection = $model->getConnection(); - $message = new $this->messageClass($model, $modelEvent); + $message = $this->builder->build($model, $modelEvent); if (true === $this->executeMiddlewares($message)) { $connection->commit(); diff --git a/src/ServiceProvider.php b/src/ServiceProvider.php index de9fb7b..7962395 100644 --- a/src/ServiceProvider.php +++ b/src/ServiceProvider.php @@ -68,7 +68,7 @@ public function register() return new ModelObserver( $middlewares, - config('transactional-event-publisher.message') + new (config('transactional-event-publisher.messageBuilder')) ); }); diff --git a/src/ValueObjects/EventMessage.php b/src/ValueObjects/EventMessage.php index 7d73560..bb1eb3a 100644 --- a/src/ValueObjects/EventMessage.php +++ b/src/ValueObjects/EventMessage.php @@ -2,54 +2,33 @@ namespace Softonic\TransactionalEventPublisher\ValueObjects; -use Illuminate\Database\Eloquent\Model; -use Softonic\TransactionalEventPublisher\Contracts\EventMessageContract; +use Softonic\TransactionalEventPublisher\Interfaces\EventMessageInterface; -class EventMessage implements EventMessageContract +class EventMessage implements EventMessageInterface { - public $service; - - public $eventType; - - public $modelName; - - public $eventName; - - public $createdAt; - - public $payload; - - public function __construct(Model $model, $eventType) - { - $this->service = config('transactional-event-publisher.service'); - $this->eventType = $eventType; - $this->modelName = class_basename($model); - $this->eventName = $this->buildEventName($this->modelName, $eventType); - $this->payload = $model->toArray(); - $this->createdAt = date('Y-m-d H:i:s'); + public function __construct( + public readonly string $service, + public readonly string $eventType, + public readonly string $modelName, + public readonly string $eventName, + public readonly array $payload, + public readonly string $createdAt, + ) { } public function toArray(): array { return [ 'service' => $this->service, + 'eventType' => $this->eventType, + 'modelName' => $this->modelName, 'eventName' => $this->eventName, - 'createdAt' => $this->createdAt, 'payload' => $this->payload, + 'createdAt' => $this->createdAt, ]; } - private function buildEventName($modelName, $event) - { - return $modelName . ucfirst($event); - } - - public function __toString(): string - { - return serialize($this->toArray()); - } - - public function jsonSerialize() + public function jsonSerialize(): array { return $this->toArray(); } diff --git a/tests/Builders/EventMessageBuilderTest.php b/tests/Builders/EventMessageBuilderTest.php new file mode 100644 index 0000000..6e79107 --- /dev/null +++ b/tests/Builders/EventMessageBuilderTest.php @@ -0,0 +1,32 @@ + ':service:']); + + $model = new TestModel(); + + Carbon::setTestNow(Carbon::parse('2021-01-01 00:00:00')); + + $eventMessage = (new EventMessageBuilder())->build($model, 'created'); + + $this->assertEquals(':service:', $eventMessage->service); + $this->assertEquals('created', $eventMessage->eventType); + $this->assertEquals('TestModel', $eventMessage->modelName); + $this->assertEquals('TestModelCreated', $eventMessage->eventName); + $this->assertEquals([], $eventMessage->payload); + $this->assertEquals('2021-01-01 00:00:00', $eventMessage->createdAt); + } +} diff --git a/tests/Console/Commands/EmitEventsTest.php b/tests/Console/Commands/EmitEventsTest.php index aaf7300..450bfcc 100644 --- a/tests/Console/Commands/EmitEventsTest.php +++ b/tests/Console/Commands/EmitEventsTest.php @@ -7,8 +7,8 @@ use Illuminate\Support\Facades\Log; use Mockery; use phpmock\mockery\PHPMockery; -use Softonic\TransactionalEventPublisher\Contracts\EventStoreMiddlewareContract; use Softonic\TransactionalEventPublisher\EventStoreMiddlewares\AmqpMiddleware; +use Softonic\TransactionalEventPublisher\Interfaces\EventStoreMiddlewareInterface; use Softonic\TransactionalEventPublisher\Models\DomainEvent; use Softonic\TransactionalEventPublisher\TestCase; @@ -16,7 +16,7 @@ class EmitEventsTest extends TestCase { use DatabaseTransactions; - private readonly EventStoreMiddlewareContract $eventPublisherMiddleware; + private readonly EventStoreMiddlewareInterface $eventPublisherMiddleware; private readonly EmitEvents $emitEvents; @@ -30,8 +30,8 @@ protected function setUp(): void config()->set('transactional-event-publisher.event_publisher_middleware', AmqpMiddleware::class); - $this->eventPublisherMiddleware = Mockery::mock(EventStoreMiddlewareContract::class); - $this->app->instance(EventStoreMiddlewareContract::class, $this->eventPublisherMiddleware); + $this->eventPublisherMiddleware = Mockery::mock(EventStoreMiddlewareInterface::class); + $this->app->instance(EventStoreMiddlewareInterface::class, $this->eventPublisherMiddleware); $this->emitEvents = new EmitEvents(); $this->emitEvents->eventPublisherMiddleware = $this->eventPublisherMiddleware; diff --git a/tests/CustomEventMessage.php b/tests/CustomEventMessage.php index 1f58768..6fb5240 100644 --- a/tests/CustomEventMessage.php +++ b/tests/CustomEventMessage.php @@ -2,30 +2,15 @@ namespace Softonic\TransactionalEventPublisher; -use Illuminate\Database\Eloquent\Model; -use Softonic\TransactionalEventPublisher\Contracts\EventMessageContract; +use Softonic\TransactionalEventPublisher\Interfaces\EventMessageInterface; -class CustomEventMessage implements EventMessageContract +class CustomEventMessage implements EventMessageInterface { - public function __construct(Model $model, $eventType) - { - } - - /** - * Returns the message in an array format. - */ public function toArray(): array { return ['test']; } - /** - * Specify data which should be serialized to JSON - * @link http://php.net/manual/en/jsonserializable.jsonserialize.php - * @return mixed data which can be serialized by json_encode, - * which is a value of any type other than a resource. - * @since 5.4.0 - */ public function jsonSerialize() { return '["test"]'; diff --git a/tests/EventStoreMiddlewares/AmqpMiddlewareTest.php b/tests/EventStoreMiddlewares/AmqpMiddlewareTest.php index cbf7042..65f80fe 100644 --- a/tests/EventStoreMiddlewares/AmqpMiddlewareTest.php +++ b/tests/EventStoreMiddlewares/AmqpMiddlewareTest.php @@ -6,8 +6,8 @@ use Mockery; use PhpAmqpLib\Message\AMQPMessage; use Softonic\Amqp\Amqp; -use Softonic\TransactionalEventPublisher\Contracts\EventMessageContract; use Softonic\TransactionalEventPublisher\Factories\AmqpMessageFactory; +use Softonic\TransactionalEventPublisher\Interfaces\EventMessageInterface; use Softonic\TransactionalEventPublisher\TestCase; class AmqpMiddlewareTest extends TestCase @@ -41,9 +41,9 @@ public function whenStoringAMessageThrowAnExceptionAmqpMiddlewareShouldReturnFal self::assertFalse($amqpMiddleware->store($message)); } - private function getOneMessage(): EventMessageContract + private function getOneMessage(): EventMessageInterface { - $message = Mockery::mock(EventMessageContract::class); + $message = Mockery::mock(EventMessageInterface::class); $message->site = 'softonic'; $message->service = 'service'; $message->eventType = 'created'; @@ -89,7 +89,7 @@ public function whenStoringMultipleMessagesThrowAnExceptionAmqpMiddlewareShouldR private function getTwoMessages(): array { - $message = Mockery::mock(EventMessageContract::class); + $message = Mockery::mock(EventMessageInterface::class); $message->site = 'softonic'; $message->service = 'service'; $message->eventType = 'updated'; diff --git a/tests/Factories/AmqpMessageFactoryTest.php b/tests/Factories/AmqpMessageFactoryTest.php index 4143546..1ec427b 100644 --- a/tests/Factories/AmqpMessageFactoryTest.php +++ b/tests/Factories/AmqpMessageFactoryTest.php @@ -6,8 +6,8 @@ use Mockery; use PhpAmqpLib\Message\AMQPMessage; use phpmock\mockery\PHPMockery; +use Softonic\TransactionalEventPublisher\Interfaces\EventMessageInterface; use Softonic\TransactionalEventPublisher\TestCase; -use Softonic\TransactionalEventPublisher\ValueObjects\EventMessage; class AmqpMessageFactoryTest extends TestCase { @@ -21,7 +21,7 @@ public function whenNoMessageShouldThrowALogicException() $factory = new AmqpMessageFactory(); - $eventMessageMock = Mockery::mock(EventMessage::class); + $eventMessageMock = Mockery::mock(EventMessageInterface::class); $eventMessageMock->shouldReceive('toArray')->once()->andReturn([]); $factory->make($eventMessageMock); @@ -33,7 +33,7 @@ public function whenNoMessageShouldThrowALogicException() public function whenRoutingKeyProvidedAndMessageShouldCreateAnAMQPMessageObject() { $factory = new AmqpMessageFactory(); - $eventMessage = Mockery::mock(EventMessage::class); + $eventMessage = Mockery::mock(EventMessageInterface::class); $eventMessage ->shouldReceive('toArray') ->andReturn(['service' => 'service', 'eventName' => 'created']); diff --git a/tests/Observers/EventMessageStub.php b/tests/Observers/EventMessageStub.php deleted file mode 100644 index 3bef8d6..0000000 --- a/tests/Observers/EventMessageStub.php +++ /dev/null @@ -1,24 +0,0 @@ -toArray(); - } -} diff --git a/tests/Observers/ModelObserverTest.php b/tests/Observers/ModelObserverTest.php index 61c7058..1deec65 100644 --- a/tests/Observers/ModelObserverTest.php +++ b/tests/Observers/ModelObserverTest.php @@ -5,8 +5,10 @@ use Illuminate\Database\Connectors\MySqlConnector; use Illuminate\Database\Eloquent\Model; use Mockery; -use Softonic\TransactionalEventPublisher\Contracts\EventStoreMiddlewareContract; use Softonic\TransactionalEventPublisher\Exceptions\EventStoreFailedException; +use Softonic\TransactionalEventPublisher\Interfaces\EventMessageBuilderInterface; +use Softonic\TransactionalEventPublisher\Interfaces\EventMessageInterface; +use Softonic\TransactionalEventPublisher\Interfaces\EventStoreMiddlewareInterface; use Softonic\TransactionalEventPublisher\TestCase; class ModelObserverTest extends TestCase @@ -16,8 +18,6 @@ class ModelObserverTest extends TestCase */ public function whenANewItemIsCreatedShouldStoreTheEventMessage() { - $eventStoreResult = true; - $mySqlConnectorMock = Mockery::mock(MySqlConnector::class); $mySqlConnectorMock->shouldReceive('beginTransaction')->once(); $mySqlConnectorMock->shouldReceive('commit')->once(); @@ -28,13 +28,11 @@ public function whenANewItemIsCreatedShouldStoreTheEventMessage() ->times(2) ->andReturn($mySqlConnectorMock); - $eventStoreMiddlewareMock = Mockery::mock(EventStoreMiddlewareContract::class); - $eventStoreMiddlewareMock - ->shouldReceive('store') - ->once() - ->andReturn($eventStoreResult); + $eventMessage = Mockery::mock(EventMessageInterface::class); + $builderMock = $this->getBuilderMock($modelMock, $eventMessage, 'created'); + $eventStoreMiddlewareMock = $this->whenEventMessageIsStored($eventMessage, true); - $modelObserver = new ModelObserver($eventStoreMiddlewareMock, EventMessageStub::class); + $modelObserver = new ModelObserver($eventStoreMiddlewareMock, $builderMock); $modelObserver->creating($modelMock); @@ -48,8 +46,6 @@ public function whenANewItemIsCreatedButTheEventStoreFailsWhenStoring() { $this->expectException(EventStoreFailedException::class); - $eventStoreResult = false; - $mySqlConnectorMock = Mockery::mock(MySqlConnector::class); $mySqlConnectorMock->shouldReceive('beginTransaction')->once(); $mySqlConnectorMock->shouldReceive('rollBack')->once(); @@ -60,13 +56,12 @@ public function whenANewItemIsCreatedButTheEventStoreFailsWhenStoring() ->times(2) ->andReturn($mySqlConnectorMock); - $eventStoreMiddlewareMock = Mockery::mock(EventStoreMiddlewareContract::class); - $eventStoreMiddlewareMock - ->shouldReceive('store') - ->once() - ->andReturn($eventStoreResult); - $modelObserver = new ModelObserver($eventStoreMiddlewareMock, EventMessageStub::class); + $eventMessage = Mockery::mock(EventMessageInterface::class); + $builderMock = $this->getBuilderMock($modelMock, $eventMessage, 'created'); + $eventStoreMiddlewareMock = $this->whenEventMessageIsStored($eventMessage, false); + + $modelObserver = new ModelObserver($eventStoreMiddlewareMock, $builderMock); $modelObserver->creating($modelMock); $modelObserver->created($modelMock); @@ -77,8 +72,6 @@ public function whenANewItemIsCreatedButTheEventStoreFailsWhenStoring() */ public function whenAnItemIsUpdatedShouldStoreTheEventMessage() { - $eventStoreResult = true; - $mySqlConnectorMock = Mockery::mock(MySqlConnector::class); $mySqlConnectorMock->shouldReceive('beginTransaction')->once(); $mySqlConnectorMock->shouldReceive('commit')->once(); @@ -89,13 +82,11 @@ public function whenAnItemIsUpdatedShouldStoreTheEventMessage() ->times(2) ->andReturn($mySqlConnectorMock); - $eventStoreMiddlewareMock = Mockery::mock(EventStoreMiddlewareContract::class); - $eventStoreMiddlewareMock - ->shouldReceive('store') - ->once() - ->andReturn($eventStoreResult); + $eventMessage = Mockery::mock(EventMessageInterface::class); + $builderMock = $this->getBuilderMock($modelMock, $eventMessage, 'updated'); + $eventStoreMiddlewareMock = $this->whenEventMessageIsStored($eventMessage, true); - $modelObserver = new ModelObserver($eventStoreMiddlewareMock, EventMessageStub::class); + $modelObserver = new ModelObserver($eventStoreMiddlewareMock, $builderMock); $modelObserver->updating($modelMock); @@ -109,8 +100,6 @@ public function whenAnItemIsUpdatedButTheEventStoreFailsWhenStoring() { $this->expectException(EventStoreFailedException::class); - $eventStoreResult = false; - $mySqlConnectorMock = Mockery::mock(MySqlConnector::class); $mySqlConnectorMock->shouldReceive('beginTransaction')->once(); $mySqlConnectorMock->shouldReceive('rollBack')->once(); @@ -121,13 +110,11 @@ public function whenAnItemIsUpdatedButTheEventStoreFailsWhenStoring() ->times(2) ->andReturn($mySqlConnectorMock); - $eventStoreMiddlewareMock = Mockery::mock(EventStoreMiddlewareContract::class); - $eventStoreMiddlewareMock - ->shouldReceive('store') - ->once() - ->andReturn($eventStoreResult); + $eventMessage = Mockery::mock(EventMessageInterface::class); + $builderMock = $this->getBuilderMock($modelMock, $eventMessage, 'updated'); + $eventStoreMiddlewareMock = $this->whenEventMessageIsStored($eventMessage, false); - $modelObserver = new ModelObserver($eventStoreMiddlewareMock, EventMessageStub::class); + $modelObserver = new ModelObserver($eventStoreMiddlewareMock, $builderMock); $modelObserver->updating($modelMock); $modelObserver->updated($modelMock); @@ -138,8 +125,6 @@ public function whenAnItemIsUpdatedButTheEventStoreFailsWhenStoring() */ public function whenAnItemDeletedShouldStoreTheEventMessage() { - $eventStoreResult = true; - $mySqlConnectorMock = Mockery::mock(MySqlConnector::class); $mySqlConnectorMock->shouldReceive('beginTransaction')->once(); $mySqlConnectorMock->shouldReceive('commit')->once(); @@ -150,13 +135,11 @@ public function whenAnItemDeletedShouldStoreTheEventMessage() ->times(2) ->andReturn($mySqlConnectorMock); - $eventStoreMiddlewareMock = Mockery::mock(EventStoreMiddlewareContract::class); - $eventStoreMiddlewareMock - ->shouldReceive('store') - ->once() - ->andReturn($eventStoreResult); + $eventMessage = Mockery::mock(EventMessageInterface::class); + $builderMock = $this->getBuilderMock($modelMock, $eventMessage, 'deleted'); + $eventStoreMiddlewareMock = $this->whenEventMessageIsStored($eventMessage, true); - $modelObserver = new ModelObserver($eventStoreMiddlewareMock, EventMessageStub::class); + $modelObserver = new ModelObserver($eventStoreMiddlewareMock, $builderMock); $modelObserver->deleting($modelMock); @@ -169,7 +152,6 @@ public function whenAnItemDeletedShouldStoreTheEventMessage() public function whenAnItemIsDeletedButTheEventStoreFailsWhenStoring() { $this->expectException(EventStoreFailedException::class); - $eventStoreResult = false; $mySqlConnectorMock = Mockery::mock(MySqlConnector::class); $mySqlConnectorMock->shouldReceive('beginTransaction')->once(); @@ -181,13 +163,11 @@ public function whenAnItemIsDeletedButTheEventStoreFailsWhenStoring() ->times(2) ->andReturn($mySqlConnectorMock); - $eventStoreMiddlewareMock = Mockery::mock(EventStoreMiddlewareContract::class); - $eventStoreMiddlewareMock - ->shouldReceive('store') - ->once() - ->andReturn($eventStoreResult); + $eventMessage = Mockery::mock(EventMessageInterface::class); + $builderMock = $this->getBuilderMock($modelMock, $eventMessage, 'deleted'); + $eventStoreMiddlewareMock = $this->whenEventMessageIsStored($eventMessage, false); - $modelObserver = new ModelObserver($eventStoreMiddlewareMock, EventMessageStub::class); + $modelObserver = new ModelObserver($eventStoreMiddlewareMock, $builderMock); $modelObserver->deleting($modelMock); $modelObserver->deleted($modelMock); @@ -198,8 +178,6 @@ public function whenAnItemIsDeletedButTheEventStoreFailsWhenStoring() */ public function whenItemIsCreatedWithMultipleMiddlewaresShouldStoreTheEventMessagesInAllTheMiddlewares() { - $eventStoreResult = true; - $mySqlConnectorMock = Mockery::mock(MySqlConnector::class); $mySqlConnectorMock->shouldReceive('beginTransaction')->once(); $mySqlConnectorMock->shouldReceive('commit')->once(); @@ -210,28 +188,50 @@ public function whenItemIsCreatedWithMultipleMiddlewaresShouldStoreTheEventMessa ->times(2) ->andReturn($mySqlConnectorMock); - $firstEventStoreMiddlewareMock = Mockery::mock(EventStoreMiddlewareContract::class); - $firstEventStoreMiddlewareMock - ->shouldReceive('store') - ->once() - ->andReturn($eventStoreResult); - - $secondEventStoreMiddlewareMock = Mockery::mock(EventStoreMiddlewareContract::class); - $secondEventStoreMiddlewareMock - ->shouldReceive('store') - ->once() - ->andReturn($eventStoreResult); + $eventMessage = Mockery::mock(EventMessageInterface::class); + $builderMock = $this->getBuilderMock($modelMock, $eventMessage, 'created'); + $firstEventStoreMiddlewareMock = $this->whenEventMessageIsStored($eventMessage, true); + $secondEventStoreMiddlewareMock = $this->whenEventMessageIsStored($eventMessage, true); $modelObserver = new ModelObserver( [ $firstEventStoreMiddlewareMock, $secondEventStoreMiddlewareMock, ], - EventMessageStub::class + $builderMock ); $modelObserver->creating($modelMock); self::assertTrue($modelObserver->created($modelMock)); } + + private function getBuilderMock( + Model $modelMock, + EventMessageInterface $eventMessage, + string $eventType + ): EventMessageBuilderInterface { + $builderMock = Mockery::mock(EventMessageBuilderInterface::class); + $builderMock + ->shouldReceive('build') + ->once() + ->with($modelMock, $eventType) + ->andReturn($eventMessage); + + return $builderMock; + } + + private function whenEventMessageIsStored( + EventMessageInterface $eventMessage, + bool $result + ): EventStoreMiddlewareInterface { + $eventStoreMiddlewareMock = Mockery::mock(EventStoreMiddlewareInterface::class); + $eventStoreMiddlewareMock + ->shouldReceive('store') + ->once() + ->with($eventMessage) + ->andReturn($result); + + return $eventStoreMiddlewareMock; + } }