diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 00000000..bc3ab5c1 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,6 @@ +version: 2 +updates: + - package-ecosystem: "composer" + directory: "/" + schedule: + interval: "daily" diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index ba672677..3e034c57 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -9,8 +9,13 @@ jobs: uses: actions/checkout@v2 - name: Docker pull run: docker-compose pull php + - name: Docker caching + uses: satackey/action-docker-layer-caching@v0.0.11 + continue-on-error: true + - name: Start PHP container + run: docker-compose up --detach --build --no-deps php - name: Run composer validate - run: docker-compose run --rm --no-deps php composer validate --strict --no-interaction --ansi + run: docker-compose exec -T php composer validate --strict --no-interaction --ansi run-php-cs-fixer: name: php-cs-fixer runs-on: ubuntu-latest @@ -19,16 +24,21 @@ jobs: uses: actions/checkout@v2 - name: Docker pull run: docker-compose pull php + - name: Docker caching + uses: satackey/action-docker-layer-caching@v0.0.11 + continue-on-error: true - name: Composer caching uses: actions/cache@v2 with: path: ./build/.composer key: ${{ runner.os }}-composer-v1-${{ hashFiles('composer.json') }} restore-keys: ${{ runner.os }}-composer-v1- + - name: Start PHP container + run: docker-compose up --detach --build --no-deps php - name: Install dependencies - run: docker-compose run --rm --no-deps php composer --no-scripts install --no-interaction --ansi + run: docker-compose exec -T php composer --no-scripts install --no-interaction --ansi - name: Run php-cs-fixer - run: docker-compose run --rm --no-deps php bin/php-cs-fixer fix --diff --dry-run --ansi --config=.php-cs-fixer.dist.php + run: docker-compose exec -T php bin/php-cs-fixer fix --diff --dry-run --ansi --config=.php-cs-fixer.dist.php run-phpunit: name: phpunit runs-on: ubuntu-latest @@ -37,22 +47,32 @@ jobs: uses: actions/checkout@v2 - name: Docker pull run: docker-compose pull + - name: Docker caching + uses: satackey/action-docker-layer-caching@v0.0.11 + continue-on-error: true - name: Composer caching uses: actions/cache@v2 with: path: ./build/.composer key: ${{ runner.os }}-composer-v1-${{ hashFiles('composer.json') }} restore-keys: ${{ runner.os }}-composer-v1- + - name: Start containers + run: docker-compose up --detach --build - name: Install dependencies - run: docker-compose run --rm php composer install --no-scripts --no-interaction --ansi + run: docker-compose exec -T php composer install --no-scripts --no-interaction --ansi - name: Run phpunit - run: docker-compose run --rm php xphp bin/phpunit --color=always --configuration=phpunit.xml.dist - - name: Upload coverage report to codecov.io - uses: codecov/codecov-action@v1 + run: docker-compose exec -T php xphp -dxdebug.mode=coverage bin/phpunit --color=always --configuration=phpunit.xml.dist + - name: Upload coverage report to Codecov.io + uses: codecov/codecov-action@v2 with: files: ./build/.phpunit/clover.xml fail_ci_if_error: true verbose: true +# - name: Upload coverage report to GitHub.com +# uses: actions/upload-artifact@v2 +# with: +# name: Code Coverage Report +# path: build/.phpunit/code-coverage/* run-rector: name: rector runs-on: ubuntu-latest @@ -61,16 +81,21 @@ jobs: uses: actions/checkout@v2 - name: Docker pull run: docker-compose pull php + - name: Docker caching + uses: satackey/action-docker-layer-caching@v0.0.11 + continue-on-error: true - name: Composer caching uses: actions/cache@v2 with: path: ./build/.composer key: ${{ runner.os }}-composer-v1-${{ hashFiles('composer.json') }} restore-keys: ${{ runner.os }}-composer-v1- + - name: Start PHP container + run: docker-compose up --detach --build --no-deps php - name: Install dependencies - run: docker-compose run --rm --no-deps php composer install --no-interaction --ansi + run: docker-compose exec -T php composer install --no-interaction --ansi - name: Run rector - run: docker-compose run --rm --no-deps php bin/rector --no-progress-bar --dry-run --ansi + run: docker-compose exec -T php bin/rector --no-progress-bar --dry-run --ansi run-deptrac: name: deptrac runs-on: ubuntu-latest @@ -79,13 +104,18 @@ jobs: uses: actions/checkout@v2 - name: Docker pull run: docker-compose pull php + - name: Docker caching + uses: satackey/action-docker-layer-caching@v0.0.11 + continue-on-error: true - name: Composer caching uses: actions/cache@v2 with: path: ./build/.composer key: ${{ runner.os }}-composer-v1-${{ hashFiles('composer.json') }} restore-keys: ${{ runner.os }}-composer-v1- + - name: Start PHP container + run: docker-compose up --detach --build --no-deps php - name: Install dependencies - run: docker-compose run --rm --no-deps php composer install --no-scripts --no-interaction --ansi + run: docker-compose exec -T php composer install --no-scripts --no-interaction --ansi - name: Run deptrac - run: docker-compose run --rm --no-deps php bin/deptrac --no-progress --no-interaction --cache-file=./build/.deptrac/.deptrac.cache --ansi + run: docker-compose exec -T php bin/deptrac --no-progress --no-interaction --cache-file=./build/.deptrac/.deptrac.cache --ansi diff --git a/.php-cs-fixer.dist.php b/.php-cs-fixer.dist.php index 3d0204ec..eb5f9850 100644 --- a/.php-cs-fixer.dist.php +++ b/.php-cs-fixer.dist.php @@ -3,6 +3,7 @@ $config = new PhpCsFixer\Config(); $finder = PhpCsFixer\Finder::create(); $finder + // The vendor directory is excluded by default. ->exclude('.github') ->exclude('bin') ->exclude('build') @@ -30,6 +31,7 @@ 'php_unit_dedicate_assert_internal_type' => true, 'php_unit_mock' => true, 'php_unit_test_case_static_method_calls' => ['call_type' => 'self'], + 'no_extra_blank_lines' => true, 'header_comment' => [ 'comment_type' => 'PHPDoc', 'location' => 'after_open', @@ -46,7 +48,6 @@ ], ] ) - //The vendor directory is excluded by default. ->setFinder($finder) ; diff --git a/README.md b/README.md index 5157ed08..293d6387 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,25 @@ -Streak ------- +![Streak](docs/images/logo.png) +------------------------------- + +[![CI](https://github.com/streakphp/streak/actions/workflows/ci.yaml/badge.svg)](https://github.com/streakphp/streak/actions/workflows/ci.yaml) [![codecov](https://codecov.io/gh/streakphp/streak/branch/master/graph/badge.svg)](https://codecov.io/gh/streakphp/streak) -Running test ------------- +Running checks & tests locally +------------------------------ + +`docker-compose up --detach --build` + +`docker-compose exec -T php composer validate --strict --no-interaction --ansi` + +`docker-compose exec -T php composer install --no-scripts --no-interaction --ansi` + +`docker-compose exec -T php xphp -dxdebug.mode=coverage bin/phpunit --color=always --configuration=phpunit.xml.dist` + +`docker-compose run -T php bin/phpunit` + +`docker-compose exec -T php bin/rector --dry-run --ansi` + +`docker-compose exec -T php bin/deptrac --no-interaction --cache-file=./build/.deptrac/.deptrac.cache --ansi` -`docker-compose run --rm php bin/phpunit` +`docker-compose exec -T php bin/php-cs-fixer fix --diff --dry-run --ansi --config=.php-cs-fixer.dist.php` diff --git a/codecov.yml b/codecov.yml index a8cd4f88..bf08d671 100644 --- a/codecov.yml +++ b/codecov.yml @@ -1,7 +1,27 @@ +codecov: + branch: master + max_report_age: 24 + require_ci_to_pass: yes + +comment: + layout: "reach, diff, flags, files" + behavior: new + require_changes: false + require_base: true + require_head: true + +parsers: + gcov: + branch_detection: + conditional: yes + loop: yes + method: yes + macro: yes + coverage: precision: 2 round: down - range: "70...100" + range: "90...100" status: project: diff --git a/composer.json b/composer.json index e9141891..178bb186 100644 --- a/composer.json +++ b/composer.json @@ -40,7 +40,7 @@ "friendsofphp/php-cs-fixer": "^3.0", "php-amqplib/rabbitmq-bundle": "^2.6.0", "phpunit/phpunit": "^9.5.4", - "rector/rector": "^0.10.19", + "rector/rector": "0.12.18", "qossmic/deptrac-shim": "^0.13.0" }, "config": { diff --git a/docker-compose.yml b/docker-compose.yml index 64c66d31..7ffe177e 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,12 +1,14 @@ -version: '3' +version: '3.7' services: php: image: streakphp/php80-cli:latest + init: true volumes: - .:/var/www/project - ./docker/php/etc/php/8.0/cli/php.ini:/etc/php/8.0/cli/php.ini working_dir: /var/www/project + entrypoint: tail -f /dev/null # keep container alive for development depends_on: - postgres - redis @@ -14,7 +16,6 @@ services: COMPOSER_ALLOW_SUPERUSER: 1 COMPOSER_NO_INTERACTION: 1 COMPOSER_CACHE_DIR: /var/www/project/build/.composer - XDEBUG_MODE: 'develop,debug,coverage' postgres: image: postgres:13-alpine diff --git a/docs/images/logo.png b/docs/images/logo.png new file mode 100644 index 00000000..49d1676b Binary files /dev/null and b/docs/images/logo.png differ diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 5c578586..376a0ff6 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -4,6 +4,8 @@ colors="true" cacheResultFile="build/.phpunit/.phpunit.result.cache" bootstrap="tests/bootstrap.php" + beStrictAboutOutputDuringTests="true" + beStrictAboutTodoAnnotatedTests="true" > @@ -11,7 +13,7 @@ - + diff --git a/rector.php b/rector.php index 6a68c12e..42b9628e 100644 --- a/rector.php +++ b/rector.php @@ -48,7 +48,6 @@ ]); // Run Rector only on changed files - $parameters->set(Option::ENABLE_CACHE, true); $parameters->set(Option::CACHE_DIR, __DIR__ . '/build/.rector'); $services = $configurator->services(); diff --git a/src/Application/Sensor.php b/src/Application/Sensor.php index df71c79a..e6128044 100644 --- a/src/Application/Sensor.php +++ b/src/Application/Sensor.php @@ -20,7 +20,7 @@ */ interface Sensor extends Producer { - public function sensorId(): Sensor\Id; + public function id(): Sensor\Id; public function process(...$messages): void; } diff --git a/src/Application/Sensor/Id.php b/src/Application/Sensor/Id.php index ccaa2523..004f56ee 100644 --- a/src/Application/Sensor/Id.php +++ b/src/Application/Sensor/Id.php @@ -13,11 +13,11 @@ namespace Streak\Application\Sensor; -use Streak\Domain\Event\Producer; +use Streak\Domain; /** * @author Alan Gabriel Bem */ -interface Id extends Producer\Id +interface Id extends Domain\Id { } diff --git a/src/Application/Sensor/Identification.php b/src/Application/Sensor/Identification.php index 5f9d6b03..222eb75d 100644 --- a/src/Application/Sensor/Identification.php +++ b/src/Application/Sensor/Identification.php @@ -14,7 +14,6 @@ namespace Streak\Application\Sensor; use Streak\Application\Sensor; -use Streak\Domain; /** * @author Alan Gabriel Bem @@ -28,21 +27,11 @@ public function __construct(Sensor\Id $id) $this->identifyBy($id); } - public function sensorId(): Sensor\Id + public function id(): Sensor\Id { return $this->id; } - public function producerId(): Domain\Id - { - return $this->sensorId(); - } - - public function id(): Domain\Id - { - return $this->sensorId(); - } - protected function identifyBy(Sensor\Id $id): void { $this->id = $id; diff --git a/src/Application/Sensor/Processing.php b/src/Application/Sensor/Processing.php index 8b72e556..9f5dcdd2 100644 --- a/src/Application/Sensor/Processing.php +++ b/src/Application/Sensor/Processing.php @@ -13,8 +13,8 @@ namespace Streak\Application\Sensor; +use Streak\Application\Sensor; use Streak\Domain\Event; -use Streak\Domain\Id; /** * @author Alan Gabriel Bem @@ -27,7 +27,7 @@ trait Processing private $events = []; private $last; - abstract public function producerId(): Id; + abstract public function id(): Sensor\Id; final public function last(): ?Event\Envelope { @@ -140,7 +140,7 @@ final public function process(...$messages): void } if (false === $routed) { - throw new \InvalidArgumentException(); + throw new \InvalidArgumentException('No method found to process message.'); } } } catch (\Throwable $e) { @@ -156,6 +156,6 @@ final public function process(...$messages): void private function addEvent(Event $event): void { - $this->pending[] = Event\Envelope::new($event, $this->producerId()); + $this->pending[] = Event\Envelope::new($event, $this->id()); } } diff --git a/src/Domain/Aggregate.php b/src/Domain/Aggregate.php index 4979bfc4..eff01c7a 100644 --- a/src/Domain/Aggregate.php +++ b/src/Domain/Aggregate.php @@ -24,5 +24,5 @@ */ interface Aggregate extends Domain\Entity { - public function aggregateId(): Domain\Aggregate\Id; + public function id(): Domain\Aggregate\Id; } diff --git a/src/Domain/Aggregate/Comparison.php b/src/Domain/Aggregate/Comparison.php index 4e57a48e..dd1e464e 100644 --- a/src/Domain/Aggregate/Comparison.php +++ b/src/Domain/Aggregate/Comparison.php @@ -19,12 +19,14 @@ /** * @author Alan Gabriel Bem + * + * @see \Streak\Domain\Aggregate\ComparisonTest */ trait Comparison { use Entity\Comparison; - abstract public function aggregateId(): Aggregate\Id; + abstract public function id(): Aggregate\Id; final public function equals(object $aggregate): bool { @@ -36,7 +38,7 @@ final public function equals(object $aggregate): bool return false; } - if (!$this->aggregateId()->equals($aggregate->aggregateId())) { + if (!$this->id()->equals($aggregate->id())) { return false; } diff --git a/src/Domain/Event/Sourced/Aggregate/Id.php b/src/Domain/Aggregate/EventSourcing.php similarity index 59% rename from src/Domain/Event/Sourced/Aggregate/Id.php rename to src/Domain/Aggregate/EventSourcing.php index 525410f5..7f6f9971 100644 --- a/src/Domain/Event/Sourced/Aggregate/Id.php +++ b/src/Domain/Aggregate/EventSourcing.php @@ -11,13 +11,19 @@ declare(strict_types=1); -namespace Streak\Domain\Event\Sourced\Aggregate; +namespace Streak\Domain\Aggregate; use Streak\Domain\Aggregate; +use Streak\Domain\Entity; /** * @author Alan Gabriel Bem + * + * @see \Streak\Domain\EventSourcingTest */ -interface Id extends Aggregate\Id +trait EventSourcing //implements Event\Sourced\Aggregate { + use Entity\EventSourcing; + + abstract public function id(): Aggregate\Id; } diff --git a/src/Domain/Aggregate/Identification.php b/src/Domain/Aggregate/Identification.php index dea44e14..e7d08c5f 100644 --- a/src/Domain/Aggregate/Identification.php +++ b/src/Domain/Aggregate/Identification.php @@ -18,6 +18,10 @@ /** * @author Alan Gabriel Bem + * + * @property $id Aggregate\Id + * + * @see \Streak\Domain\Aggregate\IdentificationTest */ trait Identification { @@ -30,7 +34,7 @@ public function __construct(Aggregate\Id $id) $this->identifyBy($id); } - public function aggregateId(): Aggregate\Id + public function id(): Aggregate\Id { return $this->id; } diff --git a/src/Domain/AggregateRoot.php b/src/Domain/AggregateRoot.php index f6346ff0..9e93bf42 100644 --- a/src/Domain/AggregateRoot.php +++ b/src/Domain/AggregateRoot.php @@ -24,5 +24,5 @@ */ interface AggregateRoot extends Domain\Aggregate { - public function aggregateRootId(): AggregateRoot\Id; + public function id(): AggregateRoot\Id; } diff --git a/src/Domain/AggregateRoot/Comparison.php b/src/Domain/AggregateRoot/Comparison.php index 8dc32b74..306b00da 100644 --- a/src/Domain/AggregateRoot/Comparison.php +++ b/src/Domain/AggregateRoot/Comparison.php @@ -19,12 +19,14 @@ /** * @author Alan Gabriel Bem + * + * @see \Streak\Domain\AggregateRoot\ComparisonTest */ trait Comparison { use Aggregate\Comparison; - abstract public function aggregateRootId(): AggregateRoot\Id; + abstract public function id(): AggregateRoot\Id; final public function equals(object $root): bool { @@ -36,7 +38,7 @@ final public function equals(object $root): bool return false; } - if (!$this->aggregateRootId()->equals($root->aggregateRootId())) { + if (!$this->id()->equals($root->id())) { return false; } diff --git a/src/Domain/AggregateRoot/EventSourcing.php b/src/Domain/AggregateRoot/EventSourcing.php new file mode 100644 index 00000000..72a73994 --- /dev/null +++ b/src/Domain/AggregateRoot/EventSourcing.php @@ -0,0 +1,140 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace Streak\Domain\AggregateRoot; + +use Streak\Domain; +use Streak\Domain\Aggregate; +use Streak\Domain\AggregateRoot; +use Streak\Domain\Event; + +/** + * @author Alan Gabriel Bem + * + * @see \Streak\Domain\EventSourcingTest + */ +trait EventSourcing //implements Event\Sourced\AggregateRoot +{ + use Aggregate\EventSourcing; + + /** + * @var Event\Envelope[] + */ + private array $events = []; + private ?Event\Envelope $lastEvent = null; + private int $version = 0; + + abstract public function id(): AggregateRoot\Id; + + /** + * @throws \Throwable + */ + final public function replay(Event\Stream $stream): void + { + foreach ($stream as $event) { + $this->applyEvent($event); + + $this->version = $event->version(); + } + + $this->events = []; + } + + final public function lastEvent(): ?Event\Envelope + { + return $this->lastEvent; + } + + final public function version(): int + { + return $this->version; + } + + /** + * @return Event\Envelope[] + */ + final public function events(): array + { + return $this->events; + } + + public function commit(): void + { + $this->version += \count($this->events); + $this->events = []; + } + + /** + * @throws Event\Exception\TooManyEventApplyingMethodsFound + * @throws Domain\Exception\EventMismatched + * @throws \Throwable + */ + final public function applyEvent(Event\Envelope $event): void + { + // $event was produced by $this aggregate or one of its embedded entities + if (!$this->id()->equals($event->producerId())) { + throw new Domain\Exception\EventMismatched($this, $event); + } + + if (null === $event->version()) { + $event = $event->defineVersion($this->version + \count($this->events) + 1); + } + + $applied = 0; + foreach ($this->eventSourcedEntities() as $entity) { + /** @var Event\Sourced\Entity $aggregate */ + if ($entity->id()->equals($event->entityId())) { + do { + try { + $entity->applyEvent($event); + $applied++; + } catch (Event\Exception\NoEventApplyingMethodFound) { + } + } while ($entity = $entity->aggregate()); + + break; // we don't need to look for next entity + } + } + + try { + $this->doApplyEvent($event); + } catch (Event\Exception\NoEventApplyingMethodFound $exception) { + if ($applied === 0) { + throw $exception; + } + } + + $this->lastEvent = $event; + $this->events[] = $event; + } + + /** + * @throws Event\Exception\NoEventApplyingMethodFound + * @throws Event\Exception\TooManyEventApplyingMethodsFound + * @throws \Throwable + */ + private function apply(Event $event): void + { + $envelope = Event\Envelope::new($event, $this->id()); + + $this->applyEvent($envelope); + } + + /** + * @return Event\Sourced\Entity[] + */ + private function eventSourcedEntities(): iterable + { + yield from Event\Sourced\Entity\Helper::for($this)->extractEventSourcedEntities(); + } +} diff --git a/src/Domain/AggregateRoot/Identification.php b/src/Domain/AggregateRoot/Identification.php index 174724ad..23878131 100644 --- a/src/Domain/AggregateRoot/Identification.php +++ b/src/Domain/AggregateRoot/Identification.php @@ -18,6 +18,10 @@ /** * @author Alan Gabriel Bem + * + * @property $id AggregateRoot\Id + * + * @see \Streak\Domain\AggregateRoot\IdentificationTest */ trait Identification { @@ -30,7 +34,7 @@ public function __construct(AggregateRoot\Id $id) $this->identifyBy($id); } - public function aggregateRootId(): AggregateRoot\Id + public function id(): AggregateRoot\Id { return $this->id; } diff --git a/src/Domain/Entity.php b/src/Domain/Entity.php index 7fe7545a..0420f936 100644 --- a/src/Domain/Entity.php +++ b/src/Domain/Entity.php @@ -18,5 +18,5 @@ */ interface Entity extends Comparable, Identifiable { - public function entityId(): Entity\Id; + public function id(): Entity\Id; } diff --git a/src/Domain/Entity/Comparison.php b/src/Domain/Entity/Comparison.php index d47d7402..3bff3810 100644 --- a/src/Domain/Entity/Comparison.php +++ b/src/Domain/Entity/Comparison.php @@ -18,10 +18,12 @@ /** * @author Alan Gabriel Bem + * + * @see \Streak\Domain\Entity\ComparisonTest */ trait Comparison { - abstract public function entityId(): Entity\Id; + abstract public function id(): Entity\Id; final public function equals(object $entity): bool { @@ -33,7 +35,7 @@ final public function equals(object $entity): bool return false; } - if (!$this->entityId()->equals($entity->entityId())) { + if (!$this->id()->equals($entity->id())) { return false; } diff --git a/src/Domain/Entity/EventSourcing.php b/src/Domain/Entity/EventSourcing.php new file mode 100644 index 00000000..327cf0e9 --- /dev/null +++ b/src/Domain/Entity/EventSourcing.php @@ -0,0 +1,86 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace Streak\Domain\Entity; + +use Streak\Domain\Entity; +use Streak\Domain\Event; +use Streak\Domain\Exception\EventMismatched; + +/** + * @author Alan Gabriel Bem + * + * @see \Streak\Domain\EventSourcingTest + */ +trait EventSourcing //implements Event\Sourced\Entity +{ + private ?Event\Sourced\AggregateRoot $aggregateRoot = null; + private ?Event\Sourced\Aggregate $aggregate = null; + + public function registerAggregateRoot(Event\Sourced\AggregateRoot $aggregateRoot): void + { + $this->aggregateRoot = $aggregateRoot; + } + + public function registerAggregate(Event\Sourced\Aggregate $aggregate): void + { + if ($this->id()->equals($aggregate->id())) { + throw new \BadMethodCallException('You can\'t register aggregate on itself.'); + } + + $this->aggregate = $aggregate; + $this->registerAggregateRoot($aggregate->aggregateRoot()); + } + + public function aggregateRoot(): Event\Sourced\AggregateRoot + { + if (null === $this->aggregateRoot) { + throw new \BadMethodCallException(sprintf('Aggregate root no registered. Did you forget to run %s::registerAggregateRoot()?', static::class)); + } + + return $this->aggregateRoot; + } + + public function aggregate(): ?Event\Sourced\Aggregate + { + return $this->aggregate; + } + + abstract public function id(): Entity\Id; + + final public function applyEvent(Event\Envelope $event): void + { + if (false === $this->aggregateRoot()->id()->equals($event->producerId())) { + throw new EventMismatched($this, $event); + } + + $this->doApplyEvent($event); + } + + /** + * @throws Event\Exception\NoEventApplyingMethodFound + * @throws Event\Exception\TooManyEventApplyingMethodsFound + * @throws \Throwable + */ + protected function apply(Event\EntityEvent $event): void + { + $event = Event\Envelope::new($event, $this->aggregateRoot()->id()); + + $this->aggregateRoot()->applyEvent($event); + } + + private function doApplyEvent(Event\Envelope $event): void + { + Event\Sourced\Entity\Helper::for($this)->applyEvent($event); + } +} diff --git a/src/Domain/Entity/Identification.php b/src/Domain/Entity/Identification.php index 4efcf70c..4131e0f2 100644 --- a/src/Domain/Entity/Identification.php +++ b/src/Domain/Entity/Identification.php @@ -13,27 +13,23 @@ namespace Streak\Domain\Entity; -use Streak\Domain; use Streak\Domain\Entity; /** * @author Alan Gabriel Bem + * + * @see \Streak\Domain\Entity\IdentificationTest */ trait Identification { - private $id; + private Entity\Id $id; public function __construct(Entity\Id $id) { $this->identifyBy($id); } - public function entityId(): Entity\Id - { - return $this->id; - } - - public function id(): Domain\Id + public function id(): Entity\Id { return $this->id; } diff --git a/src/Domain/Event/Consumer.php b/src/Domain/Event/Consumer.php index 138eef0f..45202781 100644 --- a/src/Domain/Event/Consumer.php +++ b/src/Domain/Event/Consumer.php @@ -18,7 +18,11 @@ /** * @author Alan Gabriel Bem */ -interface Consumer extends Event\Replayable +interface Consumer { - public function lastReplayed(): ?Event\Envelope; // TODO: remove (use last() instead?) + /** + * @throws Event\Exception\NoEventApplyingMethodFound + * @throws Event\Exception\TooManyEventApplyingMethodsFound + */ + public function applyEvent(Event\Envelope $event): void; } diff --git a/src/Domain/Event/Sourced/Entity/Id.php b/src/Domain/Event/EntityEvent.php similarity index 68% rename from src/Domain/Event/Sourced/Entity/Id.php rename to src/Domain/Event/EntityEvent.php index beee3e46..a7a72afe 100644 --- a/src/Domain/Event/Sourced/Entity/Id.php +++ b/src/Domain/Event/EntityEvent.php @@ -11,13 +11,12 @@ declare(strict_types=1); -namespace Streak\Domain\Event\Sourced\Entity; +namespace Streak\Domain\Event; use Streak\Domain\Entity; +use Streak\Domain\Event; -/** - * @author Alan Gabriel Bem - */ -interface Id extends Entity\Id +interface EntityEvent extends Event { + public function entityId(): Entity\Id; } diff --git a/src/Domain/Event/Envelope.php b/src/Domain/Event/Envelope.php index db1dd59f..27cdda94 100644 --- a/src/Domain/Event/Envelope.php +++ b/src/Domain/Event/Envelope.php @@ -29,6 +29,8 @@ final class Envelope implements Domain\Envelope public const METADATA_VERSION = 'version'; public const METADATA_PRODUCER_TYPE = 'producer_type'; public const METADATA_PRODUCER_ID = 'producer_id'; + public const METADATA_ENTITY_TYPE = 'entity_type'; + public const METADATA_ENTITY_ID = 'entity_id'; private array $metadata = []; public function __construct(UUID $uuid, string $name, private Event $message, Domain\Id $producerId, ?int $version = null) @@ -37,6 +39,13 @@ public function __construct(UUID $uuid, string $name, private Event $message, Do $this->metadata[self::METADATA_NAME] = $name; $this->metadata[self::METADATA_PRODUCER_TYPE] = $producerId::class; $this->metadata[self::METADATA_PRODUCER_ID] = $producerId->toString(); + if ($message instanceof EntityEvent) { + $this->metadata[self::METADATA_ENTITY_TYPE] = $message->entityId()::class; + $this->metadata[self::METADATA_ENTITY_ID] = $message->entityId()->toString(); + } else { + $this->metadata[self::METADATA_ENTITY_TYPE] = $producerId::class; + $this->metadata[self::METADATA_ENTITY_ID] = $producerId->toString(); + } if (null !== $version) { $this->metadata[self::METADATA_VERSION] = $version; } @@ -67,6 +76,11 @@ public function producerId(): Domain\Id return $this->get(self::METADATA_PRODUCER_TYPE)::fromString($this->get(self::METADATA_PRODUCER_ID)); } + public function entityId(): Domain\Id + { + return $this->get(self::METADATA_ENTITY_TYPE)::fromString($this->get(self::METADATA_ENTITY_ID)); + } + public function version(): ?int { return $this->get(self::METADATA_VERSION); @@ -77,7 +91,7 @@ public function set(string $name, $value): self if (empty($name)) { throw new \InvalidArgumentException('Name of the attribute can not be empty.'); } - if (!is_scalar($value)) { + if (!\is_scalar($value)) { throw new \InvalidArgumentException(sprintf('Value for attribute "%s" is a scalar.', $name)); } @@ -86,7 +100,8 @@ public function set(string $name, $value): self $this->name(), $this->message(), $this->producerId(), - $this->version() + $this->entityId(), + $this->version(), ); $new->metadata = $this->metadata; @@ -117,4 +132,15 @@ public function equals(object $envelope): bool return true; } + + public function defineVersion(int $version): self + { + return new self( + $this->uuid(), + $this->name(), + $this->message(), + $this->producerId(), + $version, + ); + } } diff --git a/src/Domain/Event/Exception/ConversionToObjectNotPossible.php b/src/Domain/Event/Exception/ConversionToObjectNotPossible.php index 2ae9c974..0fc93efd 100644 --- a/src/Domain/Event/Exception/ConversionToObjectNotPossible.php +++ b/src/Domain/Event/Exception/ConversionToObjectNotPossible.php @@ -18,12 +18,8 @@ */ class ConversionToObjectNotPossible extends ConversionNotPossible { - private array $array; - - public function __construct(array $array, \Throwable $previous = null) + public function __construct(private array $array, \Throwable $previous = null) { - $this->array = $array; - parent::__construct($previous); } diff --git a/src/Domain/Event/Exception/NoEventApplyingMethodFound.php b/src/Domain/Event/Exception/NoEventApplyingMethodFound.php index 43724349..ab524c09 100644 --- a/src/Domain/Event/Exception/NoEventApplyingMethodFound.php +++ b/src/Domain/Event/Exception/NoEventApplyingMethodFound.php @@ -22,14 +22,14 @@ */ class NoEventApplyingMethodFound extends \BadMethodCallException { - public function __construct(private Event\Consumer $consumer, private Event\Envelope $event, \Throwable $previous = null) + public function __construct(private object $object, private Event\Envelope $event, \Throwable $previous = null) { parent::__construct('No event applying method found.', 0, $previous); } - public function consumer(): Event\Consumer + public function object(): object { - return $this->consumer; + return $this->object; } public function event(): Event\Envelope diff --git a/src/Domain/Event/Exception/TooManyEventApplyingMethodsFound.php b/src/Domain/Event/Exception/TooManyEventApplyingMethodsFound.php index 3423f5bb..c8bb2cc3 100644 --- a/src/Domain/Event/Exception/TooManyEventApplyingMethodsFound.php +++ b/src/Domain/Event/Exception/TooManyEventApplyingMethodsFound.php @@ -22,14 +22,14 @@ */ class TooManyEventApplyingMethodsFound extends \BadMethodCallException { - public function __construct(private Event\Consumer $consumer, private Event\Envelope $event, \Throwable $previous = null) + public function __construct(private object $object, private Event\Envelope $event, \Throwable $previous = null) { parent::__construct('Too many event applying methods found.', 0, $previous); } - public function consumer(): Event\Consumer + public function object(): object { - return $this->consumer; + return $this->object; } public function event(): Event\Envelope diff --git a/src/Domain/Event/Listener.php b/src/Domain/Event/Listener.php index fa418c80..70e199f5 100644 --- a/src/Domain/Event/Listener.php +++ b/src/Domain/Event/Listener.php @@ -21,7 +21,7 @@ */ interface Listener extends Identifiable { - public function listenerId(): Listener\Id; + public function id(): Listener\Id; /** * @return bool whether event was processed/is supported diff --git a/src/Domain/Event/Listener/Identifying.php b/src/Domain/Event/Listener/Identifying.php index 55d3919c..1099d04d 100644 --- a/src/Domain/Event/Listener/Identifying.php +++ b/src/Domain/Event/Listener/Identifying.php @@ -13,7 +13,6 @@ namespace Streak\Domain\Event\Listener; -use Streak\Domain; use Streak\Domain\Event\Listener; /** @@ -28,16 +27,11 @@ public function __construct(Listener\Id $id) $this->identifyBy($id); } - public function listenerId(): Listener\Id + public function id(): Listener\Id { return $this->id; } - public function id(): Domain\Id - { - return $this->listenerId(); - } - protected function identifyBy(Listener\Id $id): void { $this->id = $id; diff --git a/src/Domain/Event/Producer.php b/src/Domain/Event/Producer.php index 7dfb9e7d..4d27c94f 100644 --- a/src/Domain/Event/Producer.php +++ b/src/Domain/Event/Producer.php @@ -21,7 +21,7 @@ */ interface Producer { - public function producerId(): Domain\Id; + public function id(): Domain\Id; /** * @return Event\Envelope[] diff --git a/src/Domain/Event/Producer/Id.php b/src/Domain/Event/Producer/Id.php deleted file mode 100644 index 40196053..00000000 --- a/src/Domain/Event/Producer/Id.php +++ /dev/null @@ -1,24 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -declare(strict_types=1); - -namespace Streak\Domain\Event\Producer; - -use Streak\Domain; - -/** - * @author Alan Gabriel Bem - */ -interface Id extends Domain\Id -{ -// public static function from(string $value) : self; -} diff --git a/src/Domain/Event/Sourced/Aggregate.php b/src/Domain/Event/Sourced/Aggregate.php index 100d3b0c..052e5808 100644 --- a/src/Domain/Event/Sourced/Aggregate.php +++ b/src/Domain/Event/Sourced/Aggregate.php @@ -19,6 +19,6 @@ /** * @author Alan Gabriel Bem */ -interface Aggregate extends Domain\Aggregate, Event\Sourced +interface Aggregate extends Domain\Aggregate, Event\Sourced\Entity { } diff --git a/src/Domain/Event/Sourced/Aggregate/Identification.php b/src/Domain/Event/Sourced/Aggregate/Identification.php deleted file mode 100644 index 68f48bb0..00000000 --- a/src/Domain/Event/Sourced/Aggregate/Identification.php +++ /dev/null @@ -1,44 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -declare(strict_types=1); - -namespace Streak\Domain\Event\Sourced\Aggregate; - -use Streak\Domain; -use Streak\Domain\Aggregate; -use Streak\Domain\Event\Producer; -use Streak\Domain\Event\Sourced as EventSourced; - -/** - * @author Alan Gabriel Bem - */ -trait Identification // implements Producer -{ - use Aggregate\Identification { - Aggregate\Identification::identifyBy as private identifyAggregateBy; - } - - public function __construct(EventSourced\Aggregate\Id $id) - { - $this->identifyBy($id); - } - - public function producerId(): Domain\Id - { - return $this->id; - } - - protected function identifyBy(Aggregate\Id $id): void - { - $this->identifyAggregateBy($id); - } -} diff --git a/src/Domain/Event/Sourced/AggregateRoot.php b/src/Domain/Event/Sourced/AggregateRoot.php index 057ebf9c..3261def3 100644 --- a/src/Domain/Event/Sourced/AggregateRoot.php +++ b/src/Domain/Event/Sourced/AggregateRoot.php @@ -20,7 +20,7 @@ /** * @author Alan Gabriel Bem */ -interface AggregateRoot extends Domain\AggregateRoot, Event\Sourced, Versionable +interface AggregateRoot extends Domain\AggregateRoot, Event\Consumer, Event\Producer, Event\Replayable, Versionable { public function lastEvent(): ?Event\Envelope; } diff --git a/src/Domain/Event/Sourced/AggregateRoot/Id.php b/src/Domain/Event/Sourced/AggregateRoot/Id.php deleted file mode 100644 index 4abdee62..00000000 --- a/src/Domain/Event/Sourced/AggregateRoot/Id.php +++ /dev/null @@ -1,23 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -declare(strict_types=1); - -namespace Streak\Domain\Event\Sourced\AggregateRoot; - -use Streak\Domain\AggregateRoot; - -/** - * @author Alan Gabriel Bem - */ -interface Id extends AggregateRoot\Id -{ -} diff --git a/src/Domain/Event/Sourced/AggregateRoot/Identification.php b/src/Domain/Event/Sourced/AggregateRoot/Identification.php deleted file mode 100644 index 583ac450..00000000 --- a/src/Domain/Event/Sourced/AggregateRoot/Identification.php +++ /dev/null @@ -1,44 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -declare(strict_types=1); - -namespace Streak\Domain\Event\Sourced\AggregateRoot; - -use Streak\Domain; -use Streak\Domain\AggregateRoot; -use Streak\Domain\Event\Producer; -use Streak\Domain\Event\Sourced as EventSourced; - -/** - * @author Alan Gabriel Bem - */ -trait Identification // implements Producer -{ - use AggregateRoot\Identification { - AggregateRoot\Identification::identifyBy as private identifyAggregateRootBy; - } - - public function __construct(EventSourced\AggregateRoot\Id $id) - { - $this->identifyBy($id); - } - - public function producerId(): Domain\Id - { - return $this->id; - } - - protected function identifyBy(AggregateRoot\Id $id): void - { - $this->identifyAggregateRootBy($id); - } -} diff --git a/src/Domain/Event/Sourced/Entity.php b/src/Domain/Event/Sourced/Entity.php index 15e44b3a..26c89f0a 100644 --- a/src/Domain/Event/Sourced/Entity.php +++ b/src/Domain/Event/Sourced/Entity.php @@ -19,6 +19,13 @@ /** * @author Alan Gabriel Bem */ -interface Entity extends Domain\Entity, Event\Sourced +interface Entity extends Domain\Entity, Event\Consumer { + public function registerAggregateRoot(Event\Sourced\AggregateRoot $aggregate): void; + + public function registerAggregate(Event\Sourced\Aggregate $aggregate): void; + + public function aggregateRoot(): Event\Sourced\AggregateRoot; + + public function aggregate(): ?Event\Sourced\Aggregate; } diff --git a/src/Domain/Event/Sourced/Entity/Helper.php b/src/Domain/Event/Sourced/Entity/Helper.php new file mode 100644 index 00000000..61e2efcf --- /dev/null +++ b/src/Domain/Event/Sourced/Entity/Helper.php @@ -0,0 +1,179 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace Streak\Domain\Event\Sourced\Entity; + +use Streak\Domain\Event; + +/** + * @author Alan Gabriel Bem + * + * @see \Streak\Domain\Event\Sourced\Entity\HelperTest + */ +final class Helper +{ + private function __construct(private object $object) + { + } + + public static function for(object $object): self + { + return new self($object); + } + + /** + * @throws Event\Exception\NoEventApplyingMethodFound + * @throws Event\Exception\TooManyEventApplyingMethodsFound + * @throws \Throwable + */ + public function applyEvent(Event\Envelope $event): void + { + self::applyEventByArgumentType($event, $this->object); + } + + /** + * @return Event\Sourced\Entity[] + */ + public function extractEventSourcedEntities(): iterable + { + yield from self::doExtractEventSourcedEntities($this->object); + } + + private static function applyEventByArgumentType(Event\Envelope $event, object &$entity): void + { + $reflection = new \ReflectionObject($entity); + + $methods = []; + foreach ($reflection->getMethods() as $method) { + // Method name must start with "apply" + if ('apply' !== mb_substr($method->getName(), 0, 5)) { + continue; + } + + // ...and have exactly one parameter... + if (1 !== $method->getNumberOfParameters()) { + continue; + } + + // ...which is required... + if (1 !== $method->getNumberOfRequiredParameters()) { + continue; + } + + $parameter = $method->getParameters()[0]; + $parameter = $parameter->getType(); + + // ...is not an union... + if (!$parameter instanceof \ReflectionNamedType) { + continue; + } + + $parameter = $parameter->getName(); + $parameter = new \ReflectionClass($parameter); + + // ..and its an event... + if (false === $parameter->isSubclassOf(Event::class)) { + continue; + } + + $target = new \ReflectionClass($event->message()); + + // .. and $event is type or subtype of defined $parameter + while ($parameter->getName() !== $target->getName()) { + $target = $target->getParentClass(); + + if (false === $target) { + continue 2; + } + } + + $methods[] = $method; + } + + if (0 === \count($methods)) { + throw new Event\Exception\NoEventApplyingMethodFound($entity, $event); + } + + // TODO: filter methods matching given event exactly and if it wont work, than filter by direct ascendants of given event and so on + + if (\count($methods) > 1) { + throw new Event\Exception\TooManyEventApplyingMethodsFound($entity, $event); + } + + $method = array_shift($methods); + + $isPublic = $method->isPublic(); + if (false === $isPublic) { + $method->setAccessible(true); + } + + try { + $method->invoke($entity, $event->message()); + } finally { + if (false === $isPublic) { + $method->setAccessible(false); + } + } + } + + /** + * Extract event sourced entities recursively. + */ + private static function doExtractEventSourcedEntities(object $object, array &$ignored = []): iterable + { + $ignored[] = $object; + + $reflection = new \ReflectionObject($object); + foreach ($reflection->getProperties() as $property) { + $public = $property->isPublic(); + + if (false === $public) { + $property->setAccessible(true); + } + + if (false === $property->isInitialized($object)) { + continue; + } + + $entity = $property->getValue($object); + + if (false === $public) { + $property->setAccessible(false); + } + + if (true === is_iterable($entity)) { + $entities = $entity; + } else { + $entities = [$entity]; + } + + foreach ($entities as $entity) { + if (!$entity instanceof Event\Sourced\Entity) { + continue; + } + + foreach ($ignored as $ignore) { + if ($entity->equals($ignore)) { + continue 2; + } + } + + yield $entity; + + foreach (self::doExtractEventSourcedEntities($entity, $ignored) as $entity) { + yield $entity; + } + } + } + } +} diff --git a/src/Domain/Event/Sourced/Entity/Identification.php b/src/Domain/Event/Sourced/Entity/Identification.php deleted file mode 100644 index 8dec9da1..00000000 --- a/src/Domain/Event/Sourced/Entity/Identification.php +++ /dev/null @@ -1,44 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -declare(strict_types=1); - -namespace Streak\Domain\Event\Sourced\Entity; - -use Streak\Domain; -use Streak\Domain\Entity; -use Streak\Domain\Event\Producer; -use Streak\Domain\Event\Sourced as EventSourced; - -/** - * @author Alan Gabriel Bem - */ -trait Identification // implements Producer -{ - use Entity\Identification { - Entity\Identification::identifyBy as private identifyEntityBy; - } - - public function __construct(EventSourced\Entity\Id $id) - { - $this->identifyBy($id); - } - - public function producerId(): Domain\Id - { - return $this->id; - } - - protected function identifyBy(Entity\Id $id): void - { - $this->identifyEntityBy($id); - } -} diff --git a/src/Domain/Event/Sourced.php b/src/Domain/Event/Sourced/Subscription.php similarity index 67% rename from src/Domain/Event/Sourced.php rename to src/Domain/Event/Sourced/Subscription.php index ca13f33a..090dc145 100644 --- a/src/Domain/Event/Sourced.php +++ b/src/Domain/Event/Sourced/Subscription.php @@ -11,14 +11,14 @@ declare(strict_types=1); -namespace Streak\Domain\Event; +namespace Streak\Domain\Event\Sourced; -use Streak\Domain\Comparable; use Streak\Domain\Event; +use Streak\Domain\Versionable; /** * @author Alan Gabriel Bem */ -interface Sourced extends Event\Producer, Event\Consumer, Comparable +interface Subscription extends Event\Subscription, Event\Producer, Event\Replayable, Versionable { } diff --git a/src/Domain/Event/Sourced/Subscription/Id.php b/src/Domain/Event/Sourced/Subscription/Id.php deleted file mode 100644 index ba95641d..00000000 --- a/src/Domain/Event/Sourced/Subscription/Id.php +++ /dev/null @@ -1,24 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -declare(strict_types=1); - -namespace Streak\Domain\Event\Sourced\Subscription; - -use Streak\Domain\Event\Subscription; -use Streak\Domain\Id\UUID; - -/** - * @author Alan Gabriel Bem - */ -class Id extends UUID implements Subscription\Id -{ -} diff --git a/src/Domain/Event/Sourcing.php b/src/Domain/Event/Sourcing.php deleted file mode 100644 index 904aa625..00000000 --- a/src/Domain/Event/Sourcing.php +++ /dev/null @@ -1,231 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -declare(strict_types=1); - -namespace Streak\Domain\Event; - -use Streak\Domain; -use Streak\Domain\Event; - -/** - * @author Alan Gabriel Bem - */ -trait Sourcing //implements Event\Consumer, Event\Producer, Domain\Identifiable, Domain\Versionable -{ - /** - * @var Event\Envelope[] - */ - private array $events = []; - private ?Event\Envelope $lastEvent = null; - private bool $replaying = false; - private ?Event\Envelope $lastReplayed = null; - private int $version = 0; - - abstract public function producerId(): Domain\Id; - - /** - * @throws \Throwable - */ - final public function replay(Event\Stream $stream): void - { - try { - $this->replaying = true; - - foreach ($stream as $event) { - $this->applyEvent($event); - } - - $this->replaying = false; - } catch (Exception\SourcingObjectWithEventFailed $exception) { - $this->replaying = false; - - throw $exception; - } - } - - final public function lastReplayed(): ?Event\Envelope - { - return $this->lastReplayed; - } - - final public function lastEvent(): ?Event\Envelope - { - return $this->lastEvent; - } - - final public function version(): int - { - return $this->version; - } - - /** - * @return Event\Envelope[] - */ - final public function events(): array - { - return $this->events; - } - - public function commit(): void - { - $this->version += \count($this->events); - $this->events = []; - } - - /** - * @throws Event\Exception\NoEventApplyingMethodFound - * @throws Event\Exception\TooManyEventApplyingMethodsFound - * @throws \Throwable - */ - private function apply(Event $event): void - { - $event = Event\Envelope::new( - $event, - $this->producerId(), - $this->version + \count($this->events) + 1 // current version + number of not committed events + 1 - ); - - $this->applyEvent($event); - } - - /** - * @throws Event\Exception\NoEventApplyingMethodFound - * @throws Event\Exception\TooManyEventApplyingMethodsFound - * @throws \Throwable - */ - private function applyEvent(Event\Envelope $event): void - { - if (!$this instanceof Event\Consumer) { - throw new Exception\SourcingObjectWithEventFailed($this, $event); - } - - if (!$this->producerId()->equals($event->producerId())) { - throw new Domain\Exception\EventAndConsumerMismatch($this, $event); - } - - try { - $version = $this->version; // backup - $last = $this->lastEvent; // backup - $lastReplayed = $this->lastReplayed; // backup - - if ($this->replaying) { - $this->lastEvent = $event; - $this->version = (int) $event->version(); - $this->lastReplayed = $event; - } else { - $this->lastEvent = $event; - $this->events[] = $event; - } - - $this->doApplyEvent($event); - } catch (\Throwable $e) { - // rollback changes - if ($this->replaying) { - $this->lastEvent = $last; - $this->version = $version; - $this->lastReplayed = $lastReplayed; - } else { - $this->lastEvent = $last; - array_pop($this->events); - } - - throw $e; - } - } - - /** - * @throws Event\Exception\NoEventApplyingMethodFound - * @throws Event\Exception\TooManyEventApplyingMethodsFound - * @throws \Throwable - */ - private function doApplyEvent(Event\Envelope $event): void - { - $reflection = new \ReflectionObject($this); - - $methods = []; - foreach ($reflection->getMethods() as $method) { - // method is not current method... - if (__FUNCTION__ === $method->getName()) { - continue; - } - - // ...and its name must start with "apply" - if ('apply' !== mb_substr($method->getName(), 0, 5)) { - continue; - } - - // ...and have exactly one parameter... - if (1 !== $method->getNumberOfParameters()) { - continue; - } - - // ...which is required... - if (1 !== $method->getNumberOfRequiredParameters()) { - continue; - } - - $parameter = $method->getParameters()[0]; - $parameter = $parameter->getType(); - - // ...is not an union... - if (!$parameter instanceof \ReflectionNamedType) { - continue; - } - - $parameter = $parameter->getName(); - $parameter = new \ReflectionClass($parameter); - - // ..and its an event... - if (false === $parameter->isSubclassOf(Event::class)) { - continue; - } - - $target = new \ReflectionClass($event->message()); - - // .. and $event is type or subtype of defined $parameter - while ($parameter->getName() !== $target->getName()) { - $target = $target->getParentClass(); - - if (false === $target) { - continue 2; - } - } - - $methods[] = $method; - } - - if (0 === \count($methods)) { - throw new Exception\NoEventApplyingMethodFound($this, $event); - } - - // TODO: filter methods matching given event exactly and if it wont work, than filter by direct ascendants of given event and so on - - if (\count($methods) > 1) { - throw new Exception\TooManyEventApplyingMethodsFound($this, $event); - } - - $method = array_shift($methods); - - $isPublic = $method->isPublic(); - if (false === $isPublic) { - $method->setAccessible(true); - } - - try { - $method->invoke($this, $event->message()); - } finally { - if (false === $isPublic) { - $method->setAccessible(false); - } - } - } -} diff --git a/src/Domain/Event/Subscription.php b/src/Domain/Event/Subscription.php index cb94d437..3526223f 100644 --- a/src/Domain/Event/Subscription.php +++ b/src/Domain/Event/Subscription.php @@ -26,7 +26,7 @@ interface Subscription { public function listener(): Event\Listener; - public function subscriptionId(): Event\Listener\Id; + public function id(): Event\Listener\Id; /** * @throws Exception\SubscriptionAlreadyCompleted diff --git a/src/Domain/Event/Subscription/Exception/SubscriptionAlreadyCompleted.php b/src/Domain/Event/Subscription/Exception/SubscriptionAlreadyCompleted.php index 4c0587bc..368f8c14 100644 --- a/src/Domain/Event/Subscription/Exception/SubscriptionAlreadyCompleted.php +++ b/src/Domain/Event/Subscription/Exception/SubscriptionAlreadyCompleted.php @@ -24,7 +24,7 @@ class SubscriptionAlreadyCompleted extends \RuntimeException implements Subscrip { public function __construct(private Subscription $subscription) { - $message = sprintf('Subscription "%s#%s" is already completed.', $this->subscription->subscriptionId()::class, $this->subscription->subscriptionId()->toString()); + $message = sprintf('Subscription "%s#%s" is already completed.', $this->subscription->id()::class, $this->subscription->id()->toString()); parent::__construct($message); } diff --git a/src/Domain/Event/Subscription/Exception/SubscriptionAlreadyStarted.php b/src/Domain/Event/Subscription/Exception/SubscriptionAlreadyStarted.php index 49f6844d..ec3f8e22 100644 --- a/src/Domain/Event/Subscription/Exception/SubscriptionAlreadyStarted.php +++ b/src/Domain/Event/Subscription/Exception/SubscriptionAlreadyStarted.php @@ -24,7 +24,7 @@ class SubscriptionAlreadyStarted extends \RuntimeException implements Subscripti { public function __construct(private Subscription $subscription) { - $id = $this->subscription->subscriptionId(); + $id = $this->subscription->id(); $message = sprintf('Subscription "%s#%s" is already started.', $id::class, $id->toString()); diff --git a/src/Domain/Event/Subscription/Exception/SubscriptionNotStartedYet.php b/src/Domain/Event/Subscription/Exception/SubscriptionNotStartedYet.php index 9044bda9..19c3dd2c 100644 --- a/src/Domain/Event/Subscription/Exception/SubscriptionNotStartedYet.php +++ b/src/Domain/Event/Subscription/Exception/SubscriptionNotStartedYet.php @@ -24,7 +24,7 @@ class SubscriptionNotStartedYet extends \RuntimeException implements Subscriptio { public function __construct(private Subscription $subscription) { - $message = sprintf('Subscription "%s#%s" is not started yet.', $this->subscription->subscriptionId()::class, $this->subscription->subscriptionId()->toString()); + $message = sprintf('Subscription "%s#%s" is not started yet.', $this->subscription->id()::class, $this->subscription->id()->toString()); parent::__construct($message); } diff --git a/src/Domain/Event/Subscription/Exception/SubscriptionPaused.php b/src/Domain/Event/Subscription/Exception/SubscriptionPaused.php index 1bd43cf6..4f925365 100644 --- a/src/Domain/Event/Subscription/Exception/SubscriptionPaused.php +++ b/src/Domain/Event/Subscription/Exception/SubscriptionPaused.php @@ -24,7 +24,7 @@ class SubscriptionPaused extends \RuntimeException implements Subscription\Excep { public function __construct(private Subscription $subscription) { - $message = sprintf('Subscription "%s#%s" is paused.', $this->subscription->subscriptionId()::class, $this->subscription->subscriptionId()->toString()); + $message = sprintf('Subscription "%s#%s" is paused.', $this->subscription->id()::class, $this->subscription->id()->toString()); parent::__construct($message); } diff --git a/src/Domain/Event/Subscription/Exception/SubscriptionRestartNotPossible.php b/src/Domain/Event/Subscription/Exception/SubscriptionRestartNotPossible.php index e495b6d5..db86d57e 100644 --- a/src/Domain/Event/Subscription/Exception/SubscriptionRestartNotPossible.php +++ b/src/Domain/Event/Subscription/Exception/SubscriptionRestartNotPossible.php @@ -24,7 +24,7 @@ class SubscriptionRestartNotPossible extends \RuntimeException implements Subscr { public function __construct(private Subscription $subscription) { - $message = sprintf('Subscription "%s#%s" restart is not possible.', $this->subscription->subscriptionId()::class, $this->subscription->subscriptionId()->toString()); + $message = sprintf('Subscription "%s#%s" restart is not possible.', $this->subscription->id()::class, $this->subscription->id()->toString()); parent::__construct($message); } diff --git a/src/Domain/Event/Subscription/Repository/Filter.php b/src/Domain/Event/Subscription/Repository/Filter.php index 963fd0f2..d6333781 100644 --- a/src/Domain/Event/Subscription/Repository/Filter.php +++ b/src/Domain/Event/Subscription/Repository/Filter.php @@ -15,6 +15,7 @@ /** * @author Alan Gabriel Bem + * @see \Streak\Domain\Event\Subscription\Repository\FilterTest */ final class Filter { diff --git a/src/Domain/Exception/EventAndConsumerMismatch.php b/src/Domain/Exception/EventMismatched.php similarity index 54% rename from src/Domain/Exception/EventAndConsumerMismatch.php rename to src/Domain/Exception/EventMismatched.php index 60746a7d..cfa74d00 100644 --- a/src/Domain/Exception/EventAndConsumerMismatch.php +++ b/src/Domain/Exception/EventMismatched.php @@ -18,18 +18,18 @@ /** * @author Alan Gabriel Bem * - * @see \Streak\Domain\Exception\EventAndConsumerMismatchTest + * @see \Streak\Domain\Exception\EventMismatchedTest */ -class EventAndConsumerMismatch extends \LogicException +class EventMismatched extends \LogicException { - public function __construct(private Event\Consumer $consumer, private Event\Envelope $event, \Throwable $previous = null) + public function __construct(private object $object, private Event\Envelope $event, \Throwable $previous = null) { - parent::__construct('Event mismatched when applying on consumer.', 0, $previous); + parent::__construct('Event mismatched when applying on object.', 0, $previous); } - public function consumer(): Event\Consumer + public function object(): object { - return $this->consumer; + return $this->object; } public function event(): Event\Envelope diff --git a/src/Infrastructure/Application/Sensor/CommittingSensor.php b/src/Infrastructure/Application/Sensor/CommittingSensor.php index 15feea21..605cea24 100644 --- a/src/Infrastructure/Application/Sensor/CommittingSensor.php +++ b/src/Infrastructure/Application/Sensor/CommittingSensor.php @@ -14,7 +14,6 @@ namespace Streak\Infrastructure\Application\Sensor; use Streak\Application\Sensor; -use Streak\Domain; use Streak\Domain\Event; use Streak\Infrastructure\Domain\UnitOfWork; @@ -29,9 +28,9 @@ public function __construct(private Sensor $sensor, private UnitOfWork $uow) { } - public function producerId(): Domain\Id + public function id(): Sensor\Id { - return $this->sensor->producerId(); + return $this->sensor->id(); } /** @@ -42,11 +41,6 @@ public function events(): array return $this->sensor->events(); } - public function sensorId(): Sensor\Id - { - return $this->sensor->sensorId(); - } - public function process(...$messages): void { $this->sensor->process(...$messages); diff --git a/src/Infrastructure/Application/Sensor/LoggingSensor.php b/src/Infrastructure/Application/Sensor/LoggingSensor.php index 7defaa3c..4d8f293a 100644 --- a/src/Infrastructure/Application/Sensor/LoggingSensor.php +++ b/src/Infrastructure/Application/Sensor/LoggingSensor.php @@ -16,7 +16,6 @@ use Psr\Log\LoggerInterface; use Streak\Application; use Streak\Application\Sensor; -use Streak\Domain; /** * @author Alan Gabriel Bem @@ -29,9 +28,9 @@ public function __construct(private Application\Sensor $sensor, private LoggerIn { } - public function producerId(): Domain\Id + public function id(): Sensor\Id { - return $this->sensor->producerId(); + return $this->sensor->id(); } public function events(): array @@ -39,11 +38,6 @@ public function events(): array return $this->sensor->events(); } - public function sensorId(): Sensor\Id - { - return $this->sensor->sensorId(); - } - public function process(...$messages): void { try { diff --git a/src/Infrastructure/Domain/AggregateRoot/Snapshotter/Storage/Exception/SnapshotNotFound.php b/src/Infrastructure/Domain/AggregateRoot/Snapshotter/Storage/Exception/SnapshotNotFound.php index e2de193d..bc809c68 100644 --- a/src/Infrastructure/Domain/AggregateRoot/Snapshotter/Storage/Exception/SnapshotNotFound.php +++ b/src/Infrastructure/Domain/AggregateRoot/Snapshotter/Storage/Exception/SnapshotNotFound.php @@ -24,7 +24,7 @@ class SnapshotNotFound extends \RuntimeException { public function __construct(private AggregateRoot $aggregate) { - parent::__construct(sprintf('Snapshot for aggregate "%s#%s" not found.', $this->aggregate->aggregateRootId()::class, $this->aggregate->aggregateRootId()->toString())); + parent::__construct(sprintf('Snapshot for aggregate "%s#%s" not found.', $this->aggregate->id()::class, $this->aggregate->id()->toString())); } public function aggregate(): AggregateRoot diff --git a/src/Infrastructure/Domain/AggregateRoot/Snapshotter/Storage/InMemoryStorage.php b/src/Infrastructure/Domain/AggregateRoot/Snapshotter/Storage/InMemoryStorage.php index da37a0f8..c88ef3cd 100644 --- a/src/Infrastructure/Domain/AggregateRoot/Snapshotter/Storage/InMemoryStorage.php +++ b/src/Infrastructure/Domain/AggregateRoot/Snapshotter/Storage/InMemoryStorage.php @@ -29,7 +29,7 @@ final class InMemoryStorage implements Snapshotter\Storage public function find(AggregateRoot $aggregate): string { foreach ($this->snapshots as [$id, $snapshot]) { - if ($aggregate->aggregateRootId()->equals($id)) { + if ($aggregate->id()->equals($id)) { return $snapshot; } } @@ -40,13 +40,13 @@ public function find(AggregateRoot $aggregate): string public function store(AggregateRoot $aggregate, string $newSnapshot): void { foreach ($this->snapshots as $key => [$id, $snapshot]) { - if ($aggregate->aggregateRootId()->equals($id)) { + if ($aggregate->id()->equals($id)) { $this->snapshots[$key] = [$id, $newSnapshot]; return; } } - $this->snapshots[] = [$aggregate->aggregateRootId(), $newSnapshot]; + $this->snapshots[] = [$aggregate->id(), $newSnapshot]; } } diff --git a/src/Infrastructure/Domain/AggregateRoot/Snapshotter/Storage/RedisStorage.php b/src/Infrastructure/Domain/AggregateRoot/Snapshotter/Storage/RedisStorage.php index 88d64cf3..af3316d1 100644 --- a/src/Infrastructure/Domain/AggregateRoot/Snapshotter/Storage/RedisStorage.php +++ b/src/Infrastructure/Domain/AggregateRoot/Snapshotter/Storage/RedisStorage.php @@ -23,11 +23,8 @@ */ final class RedisStorage implements Storage, Resettable { - private \Redis $redis; - - public function __construct(\Redis $client) + public function __construct(private \Redis $redis) { - $this->redis = $client; } /** @@ -57,9 +54,9 @@ public function reset(): bool private function key(AggregateRoot $aggregate): string { return - \get_class($aggregate). - \get_class($aggregate->aggregateRootId()). - $aggregate->aggregateRootId()->toString() + $aggregate::class. + $aggregate->id()::class. + $aggregate->id()->toString() ; } } diff --git a/src/Infrastructure/Domain/Event/Converter/NestedObjectConverter.php b/src/Infrastructure/Domain/Event/Converter/NestedObjectConverter.php index db3e1b9f..1536f27e 100644 --- a/src/Infrastructure/Domain/Event/Converter/NestedObjectConverter.php +++ b/src/Infrastructure/Domain/Event/Converter/NestedObjectConverter.php @@ -85,7 +85,7 @@ private function toArray($event): array continue; } - if (is_scalar($value)) { + if (\is_scalar($value)) { continue; } if (null === $value) { diff --git a/src/Infrastructure/Domain/Event/Listener/CompositeFactory.php b/src/Infrastructure/Domain/Event/Listener/CompositeFactory.php index 7ae95266..b736abbe 100644 --- a/src/Infrastructure/Domain/Event/Listener/CompositeFactory.php +++ b/src/Infrastructure/Domain/Event/Listener/CompositeFactory.php @@ -42,7 +42,7 @@ public function create(Listener\Id $id): Listener foreach ($this->factories as $factory) { try { return $factory->create($id); - } catch (Exception\InvalidIdGiven $e) { + } catch (Exception\InvalidIdGiven) { continue; } } diff --git a/src/Infrastructure/Domain/Event/LoggingListener.php b/src/Infrastructure/Domain/Event/LoggingListener.php index f2a57ace..a2ebe843 100644 --- a/src/Infrastructure/Domain/Event/LoggingListener.php +++ b/src/Infrastructure/Domain/Event/LoggingListener.php @@ -32,14 +32,9 @@ public function __construct(private Event\Listener $listener, private LoggerInte { } - public function id(): Domain\Id + public function id(): Listener\Id { - return $this->listenerId(); - } - - public function listenerId(): Listener\Id - { - return $this->listener->listenerId(); + return $this->listener->id(); } public function on(Event\Envelope $event): bool diff --git a/src/Infrastructure/Domain/Event/NullListener.php b/src/Infrastructure/Domain/Event/NullListener.php index a98dfa12..07c9d929 100644 --- a/src/Infrastructure/Domain/Event/NullListener.php +++ b/src/Infrastructure/Domain/Event/NullListener.php @@ -32,6 +32,6 @@ public function on(Event\Envelope $event): bool public static function from(Event\Listener $listener) { - return new self($listener->listenerId()); + return new self($listener->id()); } } diff --git a/src/Infrastructure/Domain/Event/Sourced/Subscription.php b/src/Infrastructure/Domain/Event/Sourced/Subscription.php index b74701ee..f533a16f 100644 --- a/src/Infrastructure/Domain/Event/Sourced/Subscription.php +++ b/src/Infrastructure/Domain/Event/Sourced/Subscription.php @@ -19,7 +19,6 @@ use Streak\Domain\Event\Listener\State; use Streak\Domain\Event\Subscription\Exception; use Streak\Domain\EventStore; -use Streak\Domain\Versionable; use Streak\Infrastructure\Domain\Event\InMemoryStream; use Streak\Infrastructure\Domain\Event\Sourced\Subscription\Event\SubscriptionCompleted; use Streak\Infrastructure\Domain\Event\Sourced\Subscription\Event\SubscriptionIgnoredEvent; @@ -36,12 +35,8 @@ * * @see \Streak\Infrastructure\Domain\Event\Sourced\SubscriptionTest */ -final class Subscription implements Event\Subscription, Event\Sourced, Versionable +final class Subscription implements Event\Sourced\Subscription { - use Event\Sourcing { - Event\Sourcing::replay as private doReplay; - } - private const LIMIT_TO_INITIAL_STREAM = 0; private State $lastState; private ?Event\Envelope $completedBy = null; @@ -50,11 +45,24 @@ final class Subscription implements Event\Subscription, Event\Sourced, Versionab private bool $starting = false; private $lastProcessedEvent; + /** + * @var Event\Envelope[] + */ + private array $events = []; + private ?Event\Envelope $lastEvent = null; + private bool $replaying = false; + private int $version = 0; + public function __construct(private Event\Listener $listener, private Domain\Clock $clock) { $this->lastState = InMemoryState::empty(); } + public function id(): Listener\Id + { + return $this->listener->id(); + } + /** * @throws Exception\SubscriptionAlreadyCompleted * @throws Exception\SubscriptionNotStartedYet @@ -243,7 +251,6 @@ public function replay(Event\Stream $stream): void $this->doReplay($substream); if ($this->completed()) { - $this->lastReplayed = $last; $this->lastEvent = $last; $this->version = (int) $last->version(); @@ -267,7 +274,6 @@ public function replay(Event\Stream $stream): void $this->doReplay(new InMemoryStream($changed)); } - $this->lastReplayed = $last; $this->lastEvent = $last; $this->version = (int) $last->version(); } @@ -278,23 +284,13 @@ public function equals(object $object): bool return false; } - if (!$this->subscriptionId()->equals($object->subscriptionId())) { + if (!$this->id()->equals($object->id())) { return false; } return true; } - public function producerId(): Domain\Id - { - return $this->subscriptionId(); - } - - public function subscriptionId(): Event\Listener\Id - { - return $this->listener->listenerId(); - } - public function listener(): Listener { return $this->listener; @@ -320,6 +316,45 @@ public function completed(): bool return null !== $this->completedBy; } + public function lastEvent(): ?Event\Envelope + { + return $this->lastEvent; + } + + public function version(): int + { + return $this->version; + } + + /** + * @return Event\Envelope[] + */ + public function events(): array + { + return $this->events; + } + + public function commit(): void + { + $this->version += \count($this->events); + $this->events = []; + } + + /** + * @throws \Throwable + */ + private function doReplay(Event\Stream $stream): void + { + try { + $this->replaying = true; + foreach ($stream as $event) { + $this->applyEvent($event); + } + } finally { + $this->replaying = false; + } + } + /** * @see applySubscriptionListenedToEvent * @see applySubscriptionIgnoredEvent @@ -363,46 +398,28 @@ private function doApplyEvent(Event\Envelope $event): void { if ($event->message() instanceof SubscriptionListenedToEvent) { $this->applySubscriptionListenedToEvent($event); - - return; } if ($event->message() instanceof SubscriptionIgnoredEvent) { $this->applySubscriptionIgnoredEvent($event); - - return; } if ($event->message() instanceof SubscriptionCompleted) { $this->applySubscriptionCompleted(); - - return; } if ($event->message() instanceof SubscriptionStarted) { $this->applySubscriptionStarted($event); - - return; } if ($event->message() instanceof SubscriptionRestarted) { $this->applySubscriptionRestarted($event); - - return; } if ($event->message() instanceof SubscriptionListenersStateChanged) { $this->applySubscriptionListenersStateChanged($event); - - return; } if ($event->message() instanceof SubscriptionPaused) { $this->applySubscriptionPaused($event); - - return; } if ($event->message() instanceof SubscriptionUnPaused) { $this->applySubscriptionUnPaused($event); - - return; } - - throw new Event\Exception\NoEventApplyingMethodFound($this, $event); // @codeCoverageIgnore } private function applySubscriptionListenedToEvent(Event\Envelope $event): void @@ -457,4 +474,40 @@ private function applySubscriptionListenersStateChanged(Event\Envelope $event): $this->listener->fromState($state); } } + + /** + * @throws Event\Exception\NoEventApplyingMethodFound + * @throws Event\Exception\TooManyEventApplyingMethodsFound + * @throws \Throwable + */ + private function apply(Event $event): void + { + $event = Event\Envelope::new( + $event, + $this->id(), + $this->version + \count($this->events) + 1 + ); + + $this->applyEvent($event); + } + + /** + * @throws \Throwable + */ + private function applyEvent(Event\Envelope $event): void + { + if (!$this->id()->equals($event->producerId())) { + throw new Domain\Exception\EventMismatched($this, $event); + } + + $this->doApplyEvent($event); + + $this->lastEvent = $event; + + if ($this->replaying) { + $this->version = $event->version(); + } else { + $this->events[] = $event; + } + } } diff --git a/src/Infrastructure/Domain/Event/Sourced/Subscription/InMemoryState.php b/src/Infrastructure/Domain/Event/Sourced/Subscription/InMemoryState.php index 8475e505..3364262a 100644 --- a/src/Infrastructure/Domain/Event/Sourced/Subscription/InMemoryState.php +++ b/src/Infrastructure/Domain/Event/Sourced/Subscription/InMemoryState.php @@ -102,7 +102,7 @@ private function validate(string $name, $value): void $value = [$name => $value]; array_walk_recursive($value, function ($value, $key): void { - if (true === is_scalar($value)) { + if (true === \is_scalar($value)) { return; } if (null === $value) { diff --git a/src/Infrastructure/Domain/Event/Subscription/CommittingSubscription.php b/src/Infrastructure/Domain/Event/Subscription/CommittingSubscription.php index bd84b6f6..55d6ac7f 100644 --- a/src/Infrastructure/Domain/Event/Subscription/CommittingSubscription.php +++ b/src/Infrastructure/Domain/Event/Subscription/CommittingSubscription.php @@ -34,9 +34,9 @@ public function subscription(): Subscription return $this->subscription; } - public function subscriptionId(): Event\Listener\Id + public function id(): Event\Listener\Id { - return $this->subscription->subscriptionId(); + return $this->subscription->id(); } public function listener(): Event\Listener diff --git a/src/Infrastructure/Domain/Event/Subscription/DAO/DAORepository.php b/src/Infrastructure/Domain/Event/Subscription/DAO/DAORepository.php index 489c7f21..0249f855 100644 --- a/src/Infrastructure/Domain/Event/Subscription/DAO/DAORepository.php +++ b/src/Infrastructure/Domain/Event/Subscription/DAO/DAORepository.php @@ -44,7 +44,7 @@ public function find(Event\Listener\Id $id): ?Event\Subscription public function has(Event\Subscription $subscription): bool { - return $this->dao->exists($subscription->subscriptionId()); + return $this->dao->exists($subscription->id()); } public function add(Event\Subscription $subscription): void diff --git a/src/Infrastructure/Domain/Event/Subscription/DAO/DbalPostgresDAO.php b/src/Infrastructure/Domain/Event/Subscription/DAO/DbalPostgresDAO.php index ce593c95..409ebb42 100644 --- a/src/Infrastructure/Domain/Event/Subscription/DAO/DbalPostgresDAO.php +++ b/src/Infrastructure/Domain/Event/Subscription/DAO/DbalPostgresDAO.php @@ -87,8 +87,8 @@ public function all(array $types = [], ?bool $completed = null): iterable public function toRow(DAO\Subscription $subscription): array { // dehydrate - $row['subscription_type'] = $subscription->subscriptionId()::class; - $row['subscription_id'] = $subscription->subscriptionId()->toString(); + $row['subscription_type'] = $subscription->id()::class; + $row['subscription_id'] = $subscription->id()->toString(); $row['subscription_version'] = $subscription->version(); $reflection = new \ReflectionObject($subscription); diff --git a/src/Infrastructure/Domain/Event/Subscription/DAO/IdentityMappingDao.php b/src/Infrastructure/Domain/Event/Subscription/DAO/IdentityMappingDao.php index b00a14aa..be4e54ea 100644 --- a/src/Infrastructure/Domain/Event/Subscription/DAO/IdentityMappingDao.php +++ b/src/Infrastructure/Domain/Event/Subscription/DAO/IdentityMappingDao.php @@ -83,7 +83,7 @@ public function shouldSave(Subscription $subscription): bool private function key(Subscription $subscription): string { - return sprintf('%s_%s', $subscription->subscriptionId()::class, $subscription->subscriptionId()->toString()); + return sprintf('%s_%s', $subscription->id()::class, $subscription->id()->toString()); } private function rememberVersion(Subscription $subscription): void diff --git a/src/Infrastructure/Domain/Event/Subscription/DAO/InMemoryDAO.php b/src/Infrastructure/Domain/Event/Subscription/DAO/InMemoryDAO.php index 145234dd..56360950 100644 --- a/src/Infrastructure/Domain/Event/Subscription/DAO/InMemoryDAO.php +++ b/src/Infrastructure/Domain/Event/Subscription/DAO/InMemoryDAO.php @@ -32,7 +32,7 @@ class InMemoryDAO implements DAO public function save(Subscription $subscription): void { foreach ($this->subscriptions as $key => $stored) { - if ($stored->subscriptionId()->equals($subscription->subscriptionId())) { + if ($stored->id()->equals($subscription->id())) { $this->subscriptions[$key] = $subscription; return; @@ -45,7 +45,7 @@ public function save(Subscription $subscription): void public function one(Listener\Id $id): ?Subscription { foreach ($this->subscriptions as $key => $stored) { - if ($stored->subscriptionId()->equals($id)) { + if ($stored->id()->equals($id)) { return $stored; } } @@ -62,7 +62,7 @@ public function all(array $types = [], ?bool $completed = null): iterable { foreach ($this->subscriptions as $key => $stored) { if (\count($types)) { - $type = $stored->subscriptionId()::class; + $type = $stored->id()::class; if (false === \in_array($type, $types)) { continue; } diff --git a/src/Infrastructure/Domain/Event/Subscription/DAO/Subscription.php b/src/Infrastructure/Domain/Event/Subscription/DAO/Subscription.php index c995f50e..3c09522f 100644 --- a/src/Infrastructure/Domain/Event/Subscription/DAO/Subscription.php +++ b/src/Infrastructure/Domain/Event/Subscription/DAO/Subscription.php @@ -47,9 +47,9 @@ public function listener(): Listener return $this->listener; } - public function subscriptionId(): Listener\Id + public function id(): Listener\Id { - return $this->listener->listenerId(); + return $this->listener->id(); } public function subscribeTo(EventStore $store, ?int $limit = null): iterable diff --git a/src/Infrastructure/Domain/Event/Subscription/DbalTransactionalSubscription.php b/src/Infrastructure/Domain/Event/Subscription/DbalTransactionalSubscription.php index fb34627b..84272f7d 100644 --- a/src/Infrastructure/Domain/Event/Subscription/DbalTransactionalSubscription.php +++ b/src/Infrastructure/Domain/Event/Subscription/DbalTransactionalSubscription.php @@ -40,9 +40,9 @@ public function listener(): Listener return $this->subscription->listener(); } - public function subscriptionId(): Listener\Id + public function id(): Listener\Id { - return $this->subscription->subscriptionId(); + return $this->subscription->id(); } public function subscribeTo(EventStore $store, ?int $limit = null): iterable diff --git a/src/Infrastructure/Domain/Event/Subscription/EventSourcedRepository.php b/src/Infrastructure/Domain/Event/Subscription/EventSourcedRepository.php index 0f530343..4a71a14a 100644 --- a/src/Infrastructure/Domain/Event/Subscription/EventSourcedRepository.php +++ b/src/Infrastructure/Domain/Event/Subscription/EventSourcedRepository.php @@ -43,7 +43,7 @@ public function find(Event\Listener\Id $id): ?Event\Subscription $unwrapped = $this->unwrap($subscription); $filter = new EventStore\Filter(); - $filter = $filter->filterProducerIds($unwrapped->producerId()); + $filter = $filter->filterProducerIds($unwrapped->id()); $stream = $this->store->stream($filter); @@ -66,7 +66,7 @@ public function has(Event\Subscription $subscription): bool $unwrapped = $this->unwrap($subscription); $filter = new EventStore\Filter(); - $filter = $filter->filterProducerIds($unwrapped->producerId()); + $filter = $filter->filterProducerIds($unwrapped->id()); $stream = $this->store->stream($filter); @@ -104,6 +104,7 @@ public function all(?Filter $filter = null): iterable $ids = []; foreach ($stream as $event) { + /** @var $event Event\Envelope */ if ($event->message() instanceof SubscriptionStarted) { $ids[] = $event->producerId(); } @@ -137,21 +138,18 @@ public function all(?Filter $filter = null): iterable } } - /** - * @return Event\Sourced|Subscription - */ - private function unwrap(Event\Subscription $subscription): Event\Sourced + private function unwrap(Event\Subscription $subscription): Event\Sourced\Subscription { $exception = new Exception\ObjectNotSupported($subscription); - if ($subscription instanceof Event\Sourced) { + if ($subscription instanceof Event\Sourced\Subscription) { return $subscription; } while ($subscription instanceof Subscription\Decorator) { $subscription = $subscription->subscription(); - if ($subscription instanceof Event\Sourced) { + if ($subscription instanceof Event\Sourced\Subscription) { return $subscription; } } diff --git a/src/Infrastructure/Domain/Event/Subscription/LazyLoadedSubscription.php b/src/Infrastructure/Domain/Event/Subscription/LazyLoadedSubscription.php index 92857113..bae41b48 100644 --- a/src/Infrastructure/Domain/Event/Subscription/LazyLoadedSubscription.php +++ b/src/Infrastructure/Domain/Event/Subscription/LazyLoadedSubscription.php @@ -31,7 +31,7 @@ public function __construct(private Listener\Id $id, private Subscription\Reposi { } - public function subscriptionId(): Listener\Id + public function id(): Listener\Id { return $this->id; } @@ -74,7 +74,7 @@ public function completed(): bool public function subscription(): Subscription { if (null === $this->subscription) { - $this->subscription = $this->repository->find($this->subscriptionId()); + $this->subscription = $this->repository->find($this->id()); } return $this->subscription; diff --git a/src/Infrastructure/Domain/EventStore/DbalPostgresEventStore.php b/src/Infrastructure/Domain/EventStore/DbalPostgresEventStore.php index 849201c9..ae47ce1c 100644 --- a/src/Infrastructure/Domain/EventStore/DbalPostgresEventStore.php +++ b/src/Infrastructure/Domain/EventStore/DbalPostgresEventStore.php @@ -451,7 +451,7 @@ public function event(UUID $uuid): ?Event\Envelope return $this->fromRow($row); } - public function producerId($class, $id): Domain\Id + private function toId($class, $id): Domain\Id { $reflection = new \ReflectionClass($class); @@ -643,18 +643,21 @@ private function fromRow(array $row): Event\Envelope $body = json_decode($body, true); $body = $this->converter->arrayToObject($body); - $producerId = $this->producerId($row['producer_type'], $row['producer_id']); + /* TODO: store entity type and id as columns */ + $metadata = $row['metadata']; + $metadata = json_decode($metadata, true); + + $producerId = $this->toId($row['producer_type'], $row['producer_id']); + $entityId = $this->toId($metadata['entity_type'], $metadata['entity_id']); $event = new Event\Envelope( $uuid, $row['type'], $body, $producerId, - $row['producer_version'] + $row['producer_version'], ); - $metadata = $row['metadata']; - $metadata = json_decode($metadata, true); $metadata[self::EVENT_METADATA_NUMBER] = $row['number']; foreach ($metadata as $name => $value) { @@ -702,7 +705,7 @@ private function extractIdForConcurrentWrite(UniqueConstraintViolationException return null; // @codeCoverageIgnore } - return $this->producerId($matches['type'], $matches['id']); + return $this->toId($matches['type'], $matches['id']); } private function extractIdForEventAlreadyInStore(UniqueConstraintViolationException $e) diff --git a/src/Infrastructure/Domain/Testing/AggregateRoot/Scenario.php b/src/Infrastructure/Domain/Testing/AggregateRoot/Scenario.php index c9a89012..a8fd0d2e 100644 --- a/src/Infrastructure/Domain/Testing/AggregateRoot/Scenario.php +++ b/src/Infrastructure/Domain/Testing/AggregateRoot/Scenario.php @@ -27,24 +27,14 @@ */ class Scenario implements Scenario\Given, Scenario\When, Scenario\Then { - private Domain\CommandHandler $handler; - private InMemoryEventStore $store; - private Domain\AggregateRoot\Factory $factory; - private Snapshotter $snapshotter; - private UnitOfWork $uow; private ?Domain\AggregateRoot\Id $id = null; /** * @var Domain\Event\Envelope[] */ private array $events = []; - public function __construct(Domain\CommandHandler $handler, InMemoryEventStore $store, Domain\AggregateRoot\Factory $factory, Snapshotter $snapshotter, UnitOfWork $uow) + public function __construct(private Domain\CommandHandler $handler, private InMemoryEventStore $store, private Domain\AggregateRoot\Factory $factory, private Snapshotter $snapshotter, private UnitOfWork $uow) { - $this->handler = $handler; - $this->store = $store; - $this->factory = $factory; - $this->snapshotter = $snapshotter; - $this->uow = $uow; } public function for(Domain\AggregateRoot\Id $id): Given diff --git a/src/Infrastructure/Domain/Testing/Listener/Scenario.php b/src/Infrastructure/Domain/Testing/Listener/Scenario.php index eb07458e..b7044f7e 100644 --- a/src/Infrastructure/Domain/Testing/Listener/Scenario.php +++ b/src/Infrastructure/Domain/Testing/Listener/Scenario.php @@ -28,10 +28,6 @@ */ class Scenario implements Scenario\Given, Scenario\When, Scenario\Then, Domain\CommandHandler { - private Application\CommandBus $bus; - - private Event\Listener\Factory $factory; - /** * @var Event\Envelope[] */ @@ -56,11 +52,9 @@ class Scenario implements Scenario\Given, Scenario\When, Scenario\Then, Domain\C */ private array $expectedErrors = []; - public function __construct(Application\CommandBus $bus, Event\Listener\Factory $factory) + public function __construct(private Application\CommandBus $bus, private Event\Listener\Factory $factory) { - $this->bus = $bus; $this->bus->register($this); - $this->factory = $factory; } public function given(Domain\Event ...$events): Scenario\When @@ -110,10 +104,10 @@ public function assert(callable $constraint = null): void $previousState = $currentState; $previousListener = $listener; - $listener = $this->factory->create($previousListener->listenerId()); + $listener = $this->factory->create($previousListener->id()); $listener->fromState($currentState); - Assert::assertEquals($previousListener, $listener, sprintf('Listener "%s" that listened to %s" and generated incomplete state. Please review your Listener\Stateful::toState() and Listener\Stateful::fromState() methods.', \get_class($listener), \get_class($event))); + Assert::assertEquals($previousListener, $listener, sprintf('Listener "%s" that listened to %s" and generated incomplete state. Please review your Listener\Stateful::toState() and Listener\Stateful::fromState() methods.', $listener::class, $event::class)); } $this->replaying = false; } @@ -128,7 +122,7 @@ public function assert(callable $constraint = null): void $stream = $listener->filter($stream); $stream = iterator_to_array($stream); - Assert::assertEquals([$this->when], $stream, sprintf('Listener is not listening to %s event.', \get_class($this->when))); + Assert::assertEquals([$this->when], $stream, sprintf('Listener is not listening to %s event.', $this->when::class)); } Assert::assertNotEmpty($this->expectedCommands, 'At least one then() clause is required.'); @@ -137,7 +131,7 @@ public function assert(callable $constraint = null): void $listener->on($this->when); if (!$listener instanceof Event\Listener\Stateful) { - Assert::assertEquals($listener, $new, sprintf('State introduced when listener "%s" listened to "%s" event, but listener is not implementing "%s" interface.', \get_class($listener), \get_class($this->when), Event\Listener\Stateful::class)); + Assert::assertEquals($listener, $new, sprintf('State introduced when listener "%s" listened to "%s" event, but listener is not implementing "%s" interface.', $listener::class, $this->when::class, Event\Listener\Stateful::class)); } Assert::assertEquals($this->expectedCommands, $this->actualCommands, 'Expected commands do not match actual commands dispatched by the listener.'); diff --git a/src/Infrastructure/Domain/UnitOfWork/EventStoreUnitOfWork.php b/src/Infrastructure/Domain/UnitOfWork/EventStoreUnitOfWork.php index 4e3579df..37df8a39 100644 --- a/src/Infrastructure/Domain/UnitOfWork/EventStoreUnitOfWork.php +++ b/src/Infrastructure/Domain/UnitOfWork/EventStoreUnitOfWork.php @@ -57,7 +57,7 @@ public function remove(object $producer): void foreach ($this->uncommited as $key => $current) { // @var $current Event\Producer - if ($current->producerId()->equals($producer->producerId())) { + if ($current->id()->equals($producer->id())) { unset($this->uncommited[$key]); return; @@ -73,7 +73,7 @@ public function has(object $producer): bool foreach ($this->uncommited as $current) { // @var $current Event\Producer - if ($current->producerId()->equals($producer->producerId())) { + if ($current->id()->equals($producer->id())) { return true; } } diff --git a/src/Infrastructure/Domain/UnitOfWork/SnapshottingUnitOfWork.php b/src/Infrastructure/Domain/UnitOfWork/SnapshottingUnitOfWork.php index 7dd2185d..88793707 100644 --- a/src/Infrastructure/Domain/UnitOfWork/SnapshottingUnitOfWork.php +++ b/src/Infrastructure/Domain/UnitOfWork/SnapshottingUnitOfWork.php @@ -43,7 +43,7 @@ public function add(object $producer): void $this->uow->add($producer); if ($producer instanceof Event\Sourced\AggregateRoot) { - $id = $producer->producerId(); + $id = $producer->id(); $version = $producer->version(); $this->versions->attach($id, $version); } @@ -52,7 +52,7 @@ public function add(object $producer): void public function remove(object $producer): void { if ($producer instanceof Event\Sourced\AggregateRoot) { - $id = $producer->producerId(); + $id = $producer->id(); $this->versions->offsetUnset($id); } @@ -90,10 +90,10 @@ public function commit(): \Generator continue; } - $versionBeforeCommit = $this->versions->offsetGet($committed->producerId()); + $versionBeforeCommit = $this->versions->offsetGet($committed->id()); $versionAfterCommit = $committed->version(); - $this->versions->offsetUnset($committed->producerId()); + $this->versions->offsetUnset($committed->id()); if (!$this->isReadyForSnapshot($versionBeforeCommit, $versionAfterCommit)) { yield $committed; diff --git a/src/Infrastructure/Domain/UnitOfWork/SubscriptionDAOUnitOfWork.php b/src/Infrastructure/Domain/UnitOfWork/SubscriptionDAOUnitOfWork.php index 8606b746..93fa4864 100644 --- a/src/Infrastructure/Domain/UnitOfWork/SubscriptionDAOUnitOfWork.php +++ b/src/Infrastructure/Domain/UnitOfWork/SubscriptionDAOUnitOfWork.php @@ -53,7 +53,7 @@ public function remove(object $subscription): void } foreach ($this->uncommited as $key => $current) { - if ($current->subscriptionId()->equals($subscription->subscriptionId())) { + if ($current->id()->equals($subscription->id())) { unset($this->uncommited[$key]); return; @@ -68,7 +68,7 @@ public function has(object $subscription): bool } foreach ($this->uncommited as $current) { - if ($current->subscriptionId()->equals($subscription->subscriptionId())) { + if ($current->id()->equals($subscription->id())) { return true; } } diff --git a/tests/Application/Sensor/IdentificationTest.php b/tests/Application/Sensor/IdentificationTest.php index ec8c7f2f..00a44192 100644 --- a/tests/Application/Sensor/IdentificationTest.php +++ b/tests/Application/Sensor/IdentificationTest.php @@ -34,8 +34,6 @@ public function testObject(): void { $identification = $this->getMockBuilder(Identification::class)->setConstructorArgs([$this->id])->getMockForTrait(); - self::assertSame($this->id, $identification->sensorId()); - self::assertSame($this->id, $identification->producerId()); self::assertSame($this->id, $identification->id()); } } diff --git a/tests/Application/Sensor/ProcessingTest.php b/tests/Application/Sensor/ProcessingTest.php index d088a8fd..c0d25103 100644 --- a/tests/Application/Sensor/ProcessingTest.php +++ b/tests/Application/Sensor/ProcessingTest.php @@ -47,8 +47,6 @@ public function testObject(): void $sensor = new SensorStub1($this->id); self::assertSame($this->id, $sensor->id()); - self::assertSame($this->id, $sensor->producerId()); - self::assertSame($this->id, $sensor->sensorId()); self::assertNull($sensor->last()); self::assertEmpty($sensor->events()); @@ -123,6 +121,16 @@ public function testTransactionalityOfProcessMethod(): void // no new assertions here please } + + public function testNoMethodFound(): void + { + $sensor = new SensorStub2($this->id); + + $this->expectExceptionObject(new \InvalidArgumentException('No method found to process message.')); + + $stdClass = new \stdClass(); + $sensor->process($stdClass); + } } namespace Streak\Application\Sensor\ProcessingTest; @@ -219,51 +227,36 @@ public function processStringAndThrowAnException(string $string): void class ArrayProcessed implements Event { - private array $array; - - public function __construct(array $array) + public function __construct(private array $array) { - $this->array = $array; } } class IntegerProcessed implements Event { - private int $integer; - - public function __construct(int $array) + public function __construct(private int $integer) { - $this->integer = $array; } } class StringProcessed implements Event { - private string $string; - - public function __construct(string $string) + public function __construct(private string $string) { - $this->string = $string; } } class StdClassProcessed implements Event { - private \stdClass $stdClass; - - public function __construct(\stdClass $stdClass) + public function __construct(private \stdClass $stdClass) { - $this->stdClass = $stdClass; } } class BooleanProcessed implements Event { - private bool $boolean; - - public function __construct(bool $boolean) + public function __construct(private bool $boolean) { - $this->boolean = $boolean; } } @@ -281,30 +274,21 @@ class B2 extends A class AProcessed implements Event { - private A $a; - - public function __construct(A $a) + public function __construct(private A $a) { - $this->a = $a; } } class B2Processed implements Event { - private B2 $b2; - - public function __construct(B2 $b2) + public function __construct(private B2 $b2) { - $this->b2 = $b2; } } class B1Processed implements Event { - private B1 $b1; - - public function __construct(B1 $b1) + public function __construct(private B1 $b1) { - $this->b1 = $b1; } } diff --git a/tests/Domain/Aggregate/ComparisonTest.php b/tests/Domain/Aggregate/ComparisonTest.php index 6fb44237..d0dbb9fc 100644 --- a/tests/Domain/Aggregate/ComparisonTest.php +++ b/tests/Domain/Aggregate/ComparisonTest.php @@ -81,30 +81,16 @@ public function testObject(): void use Streak\Domain; use Streak\Domain\Aggregate; -use Streak\Domain\Entity; class ComparisonStub implements Domain\Aggregate { use Aggregate\Comparison; - private Aggregate\Id $id; - - public function __construct(Aggregate\Id $id) - { - $this->id = $id; - } - - public function aggregateId(): Aggregate\Id - { - return $this->id; - } - - public function entityId(): Entity\Id + public function __construct(private Aggregate\Id $id) { - return $this->id; } - public function id(): Domain\Id + public function id(): Aggregate\Id { return $this->id; } @@ -114,19 +100,11 @@ class NonAggregateComparisonStub { use Aggregate\Comparison; - private Aggregate\Id $id; - - public function __construct(Aggregate\Id $id) + public function __construct(private Aggregate\Id $id) { - $this->id = $id; - } - - public function aggregateId(): Aggregate\Id - { - return $this->id; } - public function entityId(): Entity\Id + public function id(): Aggregate\Id { return $this->id; } diff --git a/tests/Domain/Aggregate/IdentificationTest.php b/tests/Domain/Aggregate/IdentificationTest.php index cc666325..0bd56ab6 100644 --- a/tests/Domain/Aggregate/IdentificationTest.php +++ b/tests/Domain/Aggregate/IdentificationTest.php @@ -34,8 +34,6 @@ public function testObject(): void { $identification = $this->getMockBuilder(Identification::class)->setConstructorArgs([$this->id])->getMockForTrait(); - self::assertSame($this->id, $identification->aggregateId()); - self::assertSame($this->id, $identification->entityId()); self::assertSame($this->id, $identification->id()); } } diff --git a/tests/Domain/AggregateRoot/ComparisonTest.php b/tests/Domain/AggregateRoot/ComparisonTest.php index a10127a4..11773df2 100644 --- a/tests/Domain/AggregateRoot/ComparisonTest.php +++ b/tests/Domain/AggregateRoot/ComparisonTest.php @@ -80,37 +80,17 @@ public function testObject(): void namespace Streak\Domain\AggregateRoot\ComparisonTest; use Streak\Domain; -use Streak\Domain\Aggregate; use Streak\Domain\AggregateRoot; -use Streak\Domain\Entity; class ComparisonStub implements Domain\AggregateRoot { use AggregateRoot\Comparison; - private AggregateRoot\Id $id; - - public function __construct(AggregateRoot\Id $id) - { - $this->id = $id; - } - - public function aggregateRootId(): AggregateRoot\Id - { - return $this->id; - } - - public function aggregateId(): Aggregate\Id - { - return $this->id; - } - - public function entityId(): Entity\Id + public function __construct(private AggregateRoot\Id $id) { - return $this->id; } - public function id(): Domain\Id + public function id(): AggregateRoot\Id { return $this->id; } @@ -120,24 +100,11 @@ class NonAggregateRootComparisonStub { use AggregateRoot\Comparison; - private AggregateRoot\Id $id; - - public function __construct(AggregateRoot\Id $id) - { - $this->id = $id; - } - - public function aggregateRootId(): AggregateRoot\Id + public function __construct(private AggregateRoot\Id $id) { - return $this->id; - } - - public function aggregateId(): Aggregate\Id - { - return $this->id; } - public function entityId(): Entity\Id + public function id(): AggregateRoot\Id { return $this->id; } diff --git a/tests/Domain/AggregateRoot/IdentificationTest.php b/tests/Domain/AggregateRoot/IdentificationTest.php index 59bbcc56..6dec46e8 100644 --- a/tests/Domain/AggregateRoot/IdentificationTest.php +++ b/tests/Domain/AggregateRoot/IdentificationTest.php @@ -34,9 +34,6 @@ public function testObject(): void { $identification = $this->getMockBuilder(Identification::class)->setConstructorArgs([$this->id])->getMockForTrait(); - self::assertSame($this->id, $identification->aggregateRootId()); - self::assertSame($this->id, $identification->aggregateId()); - self::assertSame($this->id, $identification->entityId()); self::assertSame($this->id, $identification->id()); } } diff --git a/tests/Domain/Entity/ComparisonTest.php b/tests/Domain/Entity/ComparisonTest.php index 64a86551..39b9b471 100644 --- a/tests/Domain/Entity/ComparisonTest.php +++ b/tests/Domain/Entity/ComparisonTest.php @@ -86,19 +86,11 @@ class ComparisonStub implements Domain\Entity { use Entity\Comparison; - private Entity\Id $id; - - public function __construct(Entity\Id $id) - { - $this->id = $id; - } - - public function entityId(): Entity\Id + public function __construct(private Entity\Id $id) { - return $this->id; } - public function id(): Domain\Id + public function id(): Entity\Id { return $this->id; } @@ -108,14 +100,11 @@ class NonEntityComparisonStub { use Entity\Comparison; - private Entity\Id $id; - - public function __construct(Entity\Id $id) + public function __construct(private Entity\Id $id) { - $this->id = $id; } - public function entityId(): Entity\Id + public function id(): Entity\Id { return $this->id; } diff --git a/tests/Domain/Entity/IdentificationTest.php b/tests/Domain/Entity/IdentificationTest.php index 434257a6..bc52992b 100644 --- a/tests/Domain/Entity/IdentificationTest.php +++ b/tests/Domain/Entity/IdentificationTest.php @@ -34,7 +34,6 @@ public function testObject(): void { $identification = $this->getMockBuilder(Identification::class)->setConstructorArgs([$this->id])->getMockForTrait(); - self::assertSame($this->id, $identification->entityId()); self::assertSame($this->id, $identification->id()); } } diff --git a/tests/Domain/Event/EnvelopeTest.php b/tests/Domain/Event/EnvelopeTest.php index a9906358..344af0e4 100644 --- a/tests/Domain/Event/EnvelopeTest.php +++ b/tests/Domain/Event/EnvelopeTest.php @@ -14,6 +14,7 @@ namespace Streak\Domain\Event; use PHPUnit\Framework\TestCase; +use Streak\Domain\Entity; use Streak\Domain\Event; use Streak\Domain\Id\UUID; @@ -25,10 +26,16 @@ class EnvelopeTest extends TestCase { private Event $event1; + private Event $event2; + private Entity\Id $entityId1; + private Entity\Id $entityId2; protected function setUp(): void { $this->event1 = $this->getMockBuilder(Event::class)->setMockClassName('dushf9fguiewhfh')->getMockForAbstractClass(); + $this->event2 = $this->getMockBuilder(Event::class)->setMockClassName('y7rb7wfe77fcw7e')->getMockForAbstractClass(); + $this->entityId1 = Event\EnvelopeTest\EntityId::random(); + $this->entityId2 = Event\EnvelopeTest\EntityId::random(); } public function testEnvelope(): void @@ -48,7 +55,7 @@ public function testEnvelope(): void self::assertSame($this->event1, $envelope1a->message()); self::assertSame(\PHP_INT_MAX, $envelope1a->version()); self::assertSame(\PHP_INT_MAX, $envelope1a->get($envelope1a::METADATA_VERSION)); - self::assertSame(['uuid' => $envelope1a->uuid()->toString(), 'name' => $envelope1a->name(), 'producer_type' => 'Streak\Domain\Id\UUID', 'producer_id' => $envelope1a->producerId()->toString(), 'version' => $envelope1a->version()], $envelope1a->metadata()); + self::assertSame(['uuid' => $envelope1a->uuid()->toString(), 'name' => $envelope1a->name(), 'producer_type' => 'Streak\Domain\Id\UUID', 'producer_id' => $envelope1a->producerId()->toString(), 'entity_type' => 'Streak\Domain\Id\UUID', 'entity_id' => $envelope1a->producerId()->toString(), 'version' => $envelope1a->version()], $envelope1a->metadata()); self::assertNull($envelope1a->get('attr-1')); $envelope1b = $envelope1a->set('attr-1', 'value-1'); @@ -56,19 +63,19 @@ public function testEnvelope(): void self::assertNotSame($envelope1a, $envelope1b); self::assertNull($envelope1a->get('attr-1')); - self::assertSame(['uuid' => $envelope1a->uuid()->toString(), 'name' => $envelope1a->name(), 'producer_type' => 'Streak\Domain\Id\UUID', 'producer_id' => $envelope1a->producerId()->toString(), 'version' => $envelope1a->version(), 'attr-1' => 'value-1'], $envelope1b->metadata()); + self::assertSame(['uuid' => $envelope1a->uuid()->toString(), 'name' => $envelope1a->name(), 'producer_type' => 'Streak\Domain\Id\UUID', 'producer_id' => $envelope1a->producerId()->toString(), 'entity_type' => 'Streak\Domain\Id\UUID', 'entity_id' => $envelope1a->producerId()->toString(), 'version' => $envelope1a->version(), 'attr-1' => 'value-1'], $envelope1b->metadata()); self::assertSame('value-1', $envelope1b->get('attr-1')); - $envelope2a = new Event\Envelope($uuid, 'dushf9fguiewhfh', $this->event1, $producerId, \PHP_INT_MAX); - $envelope2b = new Event\Envelope($uuid, 'dushf9fguiewhfh', $this->event1, $producerId, \PHP_INT_MAX); + $envelope2a = new Event\Envelope($uuid, 'dushf9fguiewhfh', $this->event1, $producerId, $producerId, \PHP_INT_MAX); + $envelope2b = new Event\Envelope($uuid, 'dushf9fguiewhfh', $this->event1, $producerId, $producerId, \PHP_INT_MAX); self::assertInstanceOf(Envelope::class, $envelope2a); - self::assertTrue($envelope2a->uuid()->equals($uuid)); + self::assertEquals($envelope2a->uuid(), $uuid); self::assertSame('dushf9fguiewhfh', $envelope2a->name()); - self::assertTrue($envelope2a->producerId()->equals($producerId)); + self::assertEquals($envelope2a->producerId(), $producerId); self::assertSame($this->event1, $envelope2a->message()); self::assertSame(\PHP_INT_MAX, $envelope2a->version()); - self::assertSame(['uuid' => $envelope2a->uuid()->toString(), 'name' => $envelope2a->name(), 'producer_type' => 'Streak\Domain\Id\UUID', 'producer_id' => $envelope2a->producerId()->toString(), 'version' => $envelope2a->version()], $envelope2a->metadata()); + self::assertSame(['uuid' => $envelope2a->uuid()->toString(), 'name' => $envelope2a->name(), 'producer_type' => 'Streak\Domain\Id\UUID', 'producer_id' => $envelope2a->producerId()->toString(), 'entity_type' => 'Streak\Domain\Id\UUID', 'entity_id' => $envelope2a->producerId()->toString(), 'version' => $envelope2a->version()], $envelope2a->metadata()); self::assertTrue($envelope1a->equals($envelope1a)); self::assertTrue($envelope2a->equals($envelope2a)); @@ -77,6 +84,38 @@ public function testEnvelope(): void self::assertTrue($envelope2a->equals($envelope2b)); self::assertFalse($envelope1a->equals(new \stdClass())); + + $envelope3 = Event\Envelope::new($this->event2, $producerId); + $envelope3 = $envelope3->defineEntityId($this->entityId2); + + self::assertNull($envelope3->version()); + self::assertSame('y7rb7wfe77fcw7e', $envelope3->name()); + self::assertEquals($envelope3->producerId(), $producerId); + self::assertEquals($envelope3->entityId(), $this->entityId2); + + $envelope4 = $envelope3->defineVersion(1); + + self::assertTrue($envelope3->equals($envelope4)); + self::assertTrue($envelope4->equals($envelope3)); + + self::assertSame(1, $envelope4->version()); + self::assertSame('y7rb7wfe77fcw7e', $envelope4->name()); + self::assertTrue($envelope4->producerId()->equals($producerId)); + self::assertTrue($envelope4->entityId()->equals($this->entityId2)); + + $envelope5 = $envelope4->defineVersion(2); + + self::assertSame(2, $envelope5->version()); + self::assertSame('y7rb7wfe77fcw7e', $envelope5->name()); + self::assertTrue($envelope5->producerId()->equals($producerId)); + self::assertTrue($envelope5->entityId()->equals($this->entityId2)); + + $envelope6 = $envelope5->defineEntityId($this->entityId2); + + self::assertSame(2, $envelope6->version()); + self::assertSame('y7rb7wfe77fcw7e', $envelope6->name()); + self::assertTrue($envelope6->producerId()->equals($producerId)); + self::assertTrue($envelope6->entityId()->equals($this->entityId2)); } public function testSettingEmptyAttributeName(): void @@ -112,3 +151,12 @@ public function testSettingNonScalarAttribute($value): void $envelope->set('attr-1', $value); } } + +namespace Streak\Domain\Event\EnvelopeTest; + +use Streak\Domain\Entity; +use Streak\Domain\Id\UUID; + +class EntityId extends UUID implements Entity\Id +{ +} diff --git a/tests/Domain/Event/Exception/AggregateAlreadyRegisteredTest.php b/tests/Domain/Event/Exception/AggregateAlreadyRegisteredTest.php index 8f787d78..ca1679ac 100644 --- a/tests/Domain/Event/Exception/AggregateAlreadyRegisteredTest.php +++ b/tests/Domain/Event/Exception/AggregateAlreadyRegisteredTest.php @@ -34,7 +34,7 @@ public function testException(): void { $exception = new AggregateAlreadyRegistered($this->aggregate); - self::assertEquals('Aggregate already registered.', $exception->getMessage()); + self::assertSame('Aggregate already registered.', $exception->getMessage()); self::assertSame($this->aggregate, $exception->aggregate()); } } diff --git a/tests/Domain/Event/Exception/EventNotSupportedTest.php b/tests/Domain/Event/Exception/EventNotSupportedTest.php index fc5abaf0..5d65ad12 100644 --- a/tests/Domain/Event/Exception/EventNotSupportedTest.php +++ b/tests/Domain/Event/Exception/EventNotSupportedTest.php @@ -30,7 +30,7 @@ class EventNotSupportedTest extends TestCase protected function setUp(): void { $producerId = $this->getMockBuilder(Domain\Id::class)->getMockForAbstractClass(); - $this->event = new Event\Envelope(UUID::random(), 'event', $this->getMockBuilder(Event::class)->getMockForAbstractClass(), $producerId, null); + $this->event = new Event\Envelope(UUID::random(), 'event', $this->getMockBuilder(Event::class)->getMockForAbstractClass(), $producerId, $producerId, null); } public function testException(): void diff --git a/tests/Domain/Event/Exception/NoEventApplyingMethodFoundTest.php b/tests/Domain/Event/Exception/NoEventApplyingMethodFoundTest.php index a83d12ee..7dba6718 100644 --- a/tests/Domain/Event/Exception/NoEventApplyingMethodFoundTest.php +++ b/tests/Domain/Event/Exception/NoEventApplyingMethodFoundTest.php @@ -24,20 +24,20 @@ */ class NoEventApplyingMethodFoundTest extends TestCase { - private Event\Consumer $consumer; + private Event\Sourced\Entity $entity; private Event\Envelope $event; protected function setUp(): void { - $this->consumer = $this->getMockBuilder(Event\Consumer::class)->getMockForAbstractClass(); - $this->event = Event\Envelope::new($this->getMockBuilder(Domain\Event::class)->getMockForAbstractClass(), Domain\Id\UUID::random()); + $this->entity = $this->getMockBuilder(Event\Sourced\Entity::class)->getMockForAbstractClass(); + $this->event = Event\Envelope::new($this->getMockBuilder(Domain\Event::class)->getMockForAbstractClass(), $producerId = Domain\Id\UUID::random()); } public function testException(): void { - $exception = new NoEventApplyingMethodFound($this->consumer, $this->event); + $exception = new NoEventApplyingMethodFound($this->entity, $this->event); - self::assertSame($this->consumer, $exception->consumer()); + self::assertSame($this->entity, $exception->object()); self::assertSame($this->event, $exception->event()); } } diff --git a/tests/Domain/Event/Exception/NotSupportedTypeTest.php b/tests/Domain/Event/Exception/NotSupportedTypeTest.php index 5d738dae..5f89f2fe 100644 --- a/tests/Domain/Event/Exception/NotSupportedTypeTest.php +++ b/tests/Domain/Event/Exception/NotSupportedTypeTest.php @@ -29,7 +29,7 @@ public function testItCreates(string $expectedMessage, $value): void { $exception = new NotSupportedType($value); self::assertEquals($value, $exception->value()); - self::assertEquals($expectedMessage, $exception->getMessage()); + self::assertSame($expectedMessage, $exception->getMessage()); } public function typesProvider(): array diff --git a/tests/Domain/Event/Exception/TooManyEventApplyingMethodsFoundTest.php b/tests/Domain/Event/Exception/TooManyEventApplyingMethodsFoundTest.php index 4f9d1daf..e9b9439c 100644 --- a/tests/Domain/Event/Exception/TooManyEventApplyingMethodsFoundTest.php +++ b/tests/Domain/Event/Exception/TooManyEventApplyingMethodsFoundTest.php @@ -24,21 +24,21 @@ */ class TooManyEventApplyingMethodsFoundTest extends TestCase { - private Event\Consumer $consumer; + private Event\Sourced\Entity $entity; private Event\Envelope $event; protected function setUp(): void { - $this->consumer = $this->getMockBuilder(Event\Consumer::class)->getMockForAbstractClass(); + $this->entity = $this->getMockBuilder(Event\Sourced\Entity::class)->getMockForAbstractClass(); $this->event = Event\Envelope::new($this->getMockBuilder(Event::class)->getMockForAbstractClass(), UUID::random()); } public function testException(): void { - $exception = new TooManyEventApplyingMethodsFound($this->consumer, $this->event); + $exception = new TooManyEventApplyingMethodsFound($this->entity, $this->event); - self::assertSame($this->consumer, $exception->consumer()); + self::assertSame($this->entity, $exception->object()); self::assertSame($this->event, $exception->event()); } } diff --git a/tests/Domain/Event/Listener/ListeningTest.php b/tests/Domain/Event/Listener/ListeningTest.php index 04edb752..ca10dbe0 100644 --- a/tests/Domain/Event/Listener/ListeningTest.php +++ b/tests/Domain/Event/Listener/ListeningTest.php @@ -309,11 +309,8 @@ class SupportedEvent3ThatCausesException implements Event } class SupportedEvent4 implements Event { - private $value; - - public function __construct($value) + public function __construct(private $value) { - $this->value = $value; } public function value() diff --git a/tests/Domain/Event/Sourced/Aggregate/IdentificationTest.php b/tests/Domain/Event/Sourced/Aggregate/IdentificationTest.php deleted file mode 100644 index fab96161..00000000 --- a/tests/Domain/Event/Sourced/Aggregate/IdentificationTest.php +++ /dev/null @@ -1,42 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -declare(strict_types=1); - -namespace Streak\Domain\Event\Sourced\Aggregate; - -use PHPUnit\Framework\TestCase; -use Streak\Domain\Event; - -/** - * @author Alan Gabriel Bem - * - * @covers \Streak\Domain\Event\Sourced\Aggregate\Identification - */ -class IdentificationTest extends TestCase -{ - private Event\Sourced\Aggregate\Id $id; - - protected function setUp(): void - { - $this->id = $this->getMockBuilder(Event\Sourced\Aggregate\Id::class)->getMockForAbstractClass(); - } - - public function testObject(): void - { - $identification = $this->getMockBuilder(Identification::class)->setConstructorArgs([$this->id])->getMockForTrait(); - - self::assertSame($this->id, $identification->producerId()); - self::assertSame($this->id, $identification->aggregateId()); - self::assertSame($this->id, $identification->entityId()); - self::assertSame($this->id, $identification->id()); - } -} diff --git a/tests/Domain/Event/Sourced/AggregateRoot/IdentificationTest.php b/tests/Domain/Event/Sourced/AggregateRoot/IdentificationTest.php deleted file mode 100644 index 52917056..00000000 --- a/tests/Domain/Event/Sourced/AggregateRoot/IdentificationTest.php +++ /dev/null @@ -1,43 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -declare(strict_types=1); - -namespace Streak\Domain\Event\Sourced\AggregateRoot; - -use PHPUnit\Framework\TestCase; -use Streak\Domain\Event; - -/** - * @author Alan Gabriel Bem - * - * @covers \Streak\Domain\Event\Sourced\AggregateRoot\Identification - */ -class IdentificationTest extends TestCase -{ - private Event\Sourced\AggregateRoot\Id $id; - - protected function setUp(): void - { - $this->id = $this->getMockBuilder(Event\Sourced\AggregateRoot\Id::class)->getMockForAbstractClass(); - } - - public function testObject(): void - { - $identification = $this->getMockBuilder(Identification::class)->setConstructorArgs([$this->id])->getMockForTrait(); - - self::assertSame($this->id, $identification->producerId()); - self::assertSame($this->id, $identification->aggregateRootId()); - self::assertSame($this->id, $identification->aggregateId()); - self::assertSame($this->id, $identification->entityId()); - self::assertSame($this->id, $identification->id()); - } -} diff --git a/tests/Domain/Event/Sourced/Entity/HelperTest.php b/tests/Domain/Event/Sourced/Entity/HelperTest.php new file mode 100644 index 00000000..56845c88 --- /dev/null +++ b/tests/Domain/Event/Sourced/Entity/HelperTest.php @@ -0,0 +1,244 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace Streak\Domain\Event\Sourced\Entity; + +use PHPUnit\Framework\TestCase; +use Streak\Domain\Event; +use Streak\Domain\Event\Sourced\Entity\HelperTest\EventSourcedEntityStub; +use Streak\Domain\Event\Sourced\Entity\HelperTest\EventSourcedEntityStubId; + +/** + * @covers \Streak\Domain\Event\Sourced\Entity\Helper + */ +class HelperTest extends TestCase +{ + public function testExtractingEventSourcedEntities(): void + { + $entity5 = new EventSourcedEntityStub(new EventSourcedEntityStubId('a1880189-03a6-43aa-963f-610002a77db5')); + $entity4 = new EventSourcedEntityStub(new EventSourcedEntityStubId('a1880189-03a6-43aa-963f-610002a77db4')); + $entity3 = new EventSourcedEntityStub(new EventSourcedEntityStubId('a1880189-03a6-43aa-963f-610002a77db3')); + $entity2 = new EventSourcedEntityStub(new EventSourcedEntityStubId('a1880189-03a6-43aa-963f-610002a77db2'), $entity3, $entity5); + $entity1 = new EventSourcedEntityStub(new EventSourcedEntityStubId('a1880189-03a6-43aa-963f-610002a77db1'), $entity2, $entity4); + + $helper = Helper::for($entity1); + + $actual = $helper->extractEventSourcedEntities(); + $actual = iterator_to_array($actual); + + $expected = [$entity2, $entity3, $entity5, $entity4]; + + self::assertSame($expected, $actual); + } + + public function testApplyingEvents(): void + { + $entity5 = new EventSourcedEntityStub(new EventSourcedEntityStubId('a1880189-03a6-43aa-963f-610002a77db5')); + $entity4 = new EventSourcedEntityStub(new EventSourcedEntityStubId('a1880189-03a6-43aa-963f-610002a77db4')); + $entity3 = new EventSourcedEntityStub(new EventSourcedEntityStubId('a1880189-03a6-43aa-963f-610002a77db3')); + $entity2 = new EventSourcedEntityStub(new EventSourcedEntityStubId('a1880189-03a6-43aa-963f-610002a77db2'), $entity3, $entity5); + $entity1 = new EventSourcedEntityStub(new EventSourcedEntityStubId('a1880189-03a6-43aa-963f-610002a77db1'), $entity2, $entity4); + + $event1 = new Event\Sourced\Entity\HelperTest\EventSourcedEntityStubEvent1(); + $event1 = Event\Envelope::new($event1, $entity1->id()); + $event2 = new Event\Sourced\Entity\HelperTest\EventSourcedEntityStubEvent2(); + $event2 = Event\Envelope::new($event2, $entity1->id()); + $event3 = new Event\Sourced\Entity\HelperTest\EventSourcedEntityStubEvent3(); + $event3 = Event\Envelope::new($event3, $entity1->id()); + $event4 = new Event\Sourced\Entity\HelperTest\EventSourcedEntityStubEvent4(); + $event4 = Event\Envelope::new($event4, $entity1->id()); + + $helper = Helper::for($entity1); + + $helper->applyEvent($event1); + + self::assertEquals([$event1->message()], $entity1->appliedEvents()); + self::assertEquals([], $entity2->appliedEvents()); + self::assertEquals([], $entity3->appliedEvents()); + self::assertEquals([], $entity4->appliedEvents()); + self::assertEquals([], $entity5->appliedEvents()); + + $helper->applyEvent($event2); + + self::assertEquals([$event1->message(), $event2->message()], $entity1->appliedEvents()); + self::assertEquals([], $entity2->appliedEvents()); + self::assertEquals([], $entity3->appliedEvents()); + self::assertEquals([], $entity4->appliedEvents()); + self::assertEquals([], $entity5->appliedEvents()); + + try { + $helper->applyEvent($event3); + self::fail(); + } catch (Event\Exception\NoEventApplyingMethodFound $exception) { + self::assertSame($event3, $exception->event()); + self::assertSame($entity1, $exception->object()); + } + + self::assertEquals([$event1->message(), $event2->message()], $entity1->appliedEvents()); + self::assertEquals([], $entity2->appliedEvents()); + self::assertEquals([], $entity3->appliedEvents()); + self::assertEquals([], $entity4->appliedEvents()); + self::assertEquals([], $entity5->appliedEvents()); + + $this->expectExceptionObject(new Event\Exception\TooManyEventApplyingMethodsFound($entity1, $event4)); + + try { + $helper->applyEvent($event4); + self::fail(); + } catch (Event\Exception\TooManyEventApplyingMethodsFound $exception) { + self::assertSame($event4, $exception->event()); + self::assertSame($entity1, $exception->object()); + self::assertEquals([$event1->message(), $event2->message()], $entity1->appliedEvents()); + self::assertEquals([], $entity2->appliedEvents()); + self::assertEquals([], $entity3->appliedEvents()); + self::assertEquals([], $entity4->appliedEvents()); + self::assertEquals([], $entity5->appliedEvents()); + + throw $exception; + } + } +} + +namespace Streak\Domain\Event\Sourced\Entity\HelperTest; + +use Streak\Domain\Entity; +use Streak\Domain\Event; +use Streak\Domain\Id\UUID; + +final class EventSourcedEntityStubId extends UUID implements Entity\Id +{ +} + +final class EventSourcedEntityStub implements Event\Sourced\Entity +{ + use Entity\Comparison; + + private self $self; + private int $integer; + private string $string; + private object $object; + private array $arrayOfIntegers; + private array $arrayOfStrings; + private array $arrayOfObjects; + private array $arrayOfMixed; + private string $nonInitializedString; + private int $nonInitializedInteger; + private object $nonInitializedObject; + private array $nonInitializedArray; + + /** + * @var Event\Envelope[] + */ + private array $appliedEvents = []; + + public function __construct(private EventSourcedEntityStubId $id, private ?self $entity = null, ?self $entity2 = null) + { + $this->self = $this; + $this->integer = 1; + $this->string = 'string'; + $this->object = new \stdClass(); + $this->arrayOfIntegers = [-1, 0, 1]; + $this->arrayOfStrings = ['string 1', 'string 2']; + $this->arrayOfObjects = [new \stdClass(), new \stdClass()]; + $this->arrayOfMixed = [-1, 0, 1, 'string 1', 'string 2', new \stdClass(), new \stdClass(), $this, $entity, $entity2, null]; + } + + public function id(): Entity\Id + { + return $this->id; + } + + public function appliedEvents(): array + { + return $this->appliedEvents; + } + + public function applyEvent(Event\Envelope $event): void + { + throw new \RuntimeException(__METHOD__ . ' should not be invoked.'); + } + + public function registerAggregateRoot(Event\Sourced\AggregateRoot $aggregate): void + { + throw new \RuntimeException(__METHOD__ . ' should not be invoked.'); + } + + public function registerAggregate(Event\Sourced\Aggregate $aggregate): void + { + throw new \RuntimeException(__METHOD__ . ' should not be invoked.'); + } + + public function aggregateRoot(): Event\Sourced\AggregateRoot + { + throw new \RuntimeException(__METHOD__ . ' should not be invoked.'); + } + + public function aggregate(): ?Event\Sourced\Aggregate + { + throw new \RuntimeException(__METHOD__ . ' should not be invoked.'); + } + + private function applyEventSourcedEntityStubEvent1(EventSourcedEntityStubEvent1 $event): bool + { + $this->appliedEvents[] = $event; + + return true; + } + + private function applyEventSourcedEntityStubEvent2(EventSourcedEntityStubEvent2 $event): bool + { + $this->appliedEvents[] = $event; + + return true; + } + + private function applyEventSourcedEntityStubEvent4a(EventSourcedEntityStubEvent4 $event): bool + { + throw new \RuntimeException(__METHOD__ . ' should not be invoked.'); + } + + private function applyEventSourcedEntityStubEvent4b(EventSourcedEntityStubEvent4 $event): bool + { + throw new \RuntimeException(__METHOD__ . ' should not be invoked.'); + } + + private function applyTwoArgumentsAtOnce(int $arg1, int $arg2): bool + { + throw new \RuntimeException(__METHOD__ . ' should not be invoked.'); + } + + private function applyNonRequiredArguments(int $arg1 = null): bool + { + throw new \RuntimeException(__METHOD__ . ' should not be invoked.'); + } + + private function applyMixedArguments($arg1): bool + { + throw new \RuntimeException(__METHOD__ . ' should not be invoked.'); + } +} + +class EventSourcedEntityStubEvent1 implements Event +{ +} + +class EventSourcedEntityStubEvent2 implements Event +{ +} + +class EventSourcedEntityStubEvent3 implements Event +{ +} +class EventSourcedEntityStubEvent4 implements Event +{ +} diff --git a/tests/Domain/Event/Sourced/Entity/IdentificationTest.php b/tests/Domain/Event/Sourced/Entity/IdentificationTest.php deleted file mode 100644 index 6fd98adf..00000000 --- a/tests/Domain/Event/Sourced/Entity/IdentificationTest.php +++ /dev/null @@ -1,41 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -declare(strict_types=1); - -namespace Streak\Domain\Event\Sourced\Entity; - -use PHPUnit\Framework\TestCase; -use Streak\Domain\Event; - -/** - * @author Alan Gabriel Bem - * - * @covers \Streak\Domain\Event\Sourced\Entity\Identification - */ -class IdentificationTest extends TestCase -{ - private Event\Sourced\Entity\Id $id; - - protected function setUp(): void - { - $this->id = $this->getMockBuilder(Event\Sourced\Entity\Id::class)->getMockForAbstractClass(); - } - - public function testObject(): void - { - $identification = $this->getMockBuilder(Identification::class)->setConstructorArgs([$this->id])->getMockForTrait(); - - self::assertSame($this->id, $identification->producerId()); - self::assertSame($this->id, $identification->entityId()); - self::assertSame($this->id, $identification->id()); - } -} diff --git a/tests/Domain/Event/SourcingTest.php b/tests/Domain/Event/SourcingTest.php deleted file mode 100644 index 38fdaa10..00000000 --- a/tests/Domain/Event/SourcingTest.php +++ /dev/null @@ -1,449 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -declare(strict_types=1); - -namespace Streak\Domain\Event; - -use PHPUnit\Framework\TestCase; -use Streak\Domain; -use Streak\Domain\AggregateRoot; -use Streak\Domain\Event; -use Streak\Infrastructure\Domain\Event\InMemoryStream; - -/** - * @author Alan Gabriel Bem - * - * @covers \Streak\Domain\Event\Sourcing - */ -class SourcingTest extends TestCase -{ - private AggregateRoot\Id $id1; - - private AggregateRoot\Id $id2; - - private Event\Envelope $event1; - - private Event\Envelope $event2; - - protected function setUp(): void - { - $this->id1 = new class('f5e65690-e50d-4312-a175-b004ec1bd42a') extends Domain\Id\UUID implements AggregateRoot\Id { - }; - $this->id2 = new class('f84d8230-90a8-416f-af09-5ba315214888') extends Domain\Id\UUID implements AggregateRoot\Id { - }; - $this->event1 = Event\Envelope::new($this->getMockBuilder(Event::class)->setMockClassName('event1')->getMockForAbstractClass(), $this->id1, 1); - $this->event2 = Event\Envelope::new($this->getMockBuilder(Event::class)->setMockClassName('event2')->getMockForAbstractClass(), $this->id2, 1); - } - - public function testSuccessfullyApplyingEventWithPublicHandlingMethod(): void - { - $event = new SourcingTest\EventStubForTestingPublicHandlingMethod(); - $event = Event\Envelope::new($event, $this->id1, 1); - - $sourcing = new SourcingTest\EventSourcedAggregateRootStub($this->id1); - - self::assertFalse($sourcing->isEventStubForTestingPublicHandlingMethodApplied()); - self::assertNull($sourcing->lastReplayed()); - self::assertNull($sourcing->lastEvent()); - self::assertEquals(0, $sourcing->version()); - self::assertEmpty($sourcing->events()); - - $sourcing->replay(new InMemoryStream($event)); - - self::assertTrue($sourcing->isEventStubForTestingPublicHandlingMethodApplied()); - self::assertSame($event, $sourcing->lastReplayed()); - self::assertEquals($event, $sourcing->lastEvent()); - self::assertEquals(1, $sourcing->version()); - self::assertEmpty($sourcing->events()); - - $sourcing->commit(); - - self::assertTrue($sourcing->isEventStubForTestingPublicHandlingMethodApplied()); - self::assertSame($event, $sourcing->lastReplayed()); - self::assertEquals($event, $sourcing->lastEvent()); - self::assertEquals(1, $sourcing->version()); - self::assertEmpty($sourcing->events()); - } - - public function testSuccessfullyApplyingEventWithNonPublicHandlingMethod(): void - { - $event = new SourcingTest\EventStubForTestingNonPublicHandlingMethod(); - $event = Event\Envelope::new($event, $this->id1, 1); - $sourcing = new SourcingTest\EventSourcedAggregateRootStub($this->id1); - - self::assertFalse($sourcing->isEventStubForTestingNonPublicHandlingMethodApplied()); - - $sourcing->replay(new InMemoryStream($event)); - - self::assertTrue($sourcing->isEventStubForTestingNonPublicHandlingMethodApplied()); - self::assertSame($event, $sourcing->lastReplayed()); - self::assertEquals($event, $sourcing->lastEvent()); - self::assertEquals(1, $sourcing->version()); - self::assertEmpty($sourcing->events()); - } - - public function testAggregateWithMissingHandlingMethodForGivenEvent(): void - { - $event = new SourcingTest\EventStubForTestingMissingHandlingMethod(); - $event = Event\Envelope::new($event, $this->id1, 1); - $sourcing = new SourcingTest\EventSourcedAggregateRootStub($this->id1); - - $exception = new Domain\Event\Exception\NoEventApplyingMethodFound($sourcing, $event); - $this->expectExceptionObject($exception); - - $sourcing->replay(new InMemoryStream($event)); - } - - public function testAggregateWithTwoOrMoreHandlingMethodsPresentForGivenEvent(): void - { - $event = new SourcingTest\EventStubForTestingTwoOrMoreHandlingMethodsPresent(); - $event = Event\Envelope::new($event, $this->id1, 1); - $sourcing = new SourcingTest\EventSourcedAggregateRootStub($this->id1); - - $exception = new Domain\Event\Exception\TooManyEventApplyingMethodsFound($sourcing, $event); - $this->expectExceptionObject($exception); - - $sourcing->replay(new InMemoryStream($event)); - } - - public function testAggregateWithTwoOrMoreParametersPresentOnHandlingMethod(): void - { - $event = new SourcingTest\EventStubForTestingTwoOrMoreParametersPresentOnHandlingMethod(); - $event = Event\Envelope::new($event, $this->id1, 1); - $sourcing = new SourcingTest\EventSourcedAggregateRootStub($this->id1); - - $exception = new Domain\Event\Exception\NoEventApplyingMethodFound($sourcing, $event); - $this->expectExceptionObject($exception); - - $sourcing->replay(new InMemoryStream($event)); - } - - public function testAggregateWithOptionalParameterOnHandlingMethodForGivenEvent(): void - { - $event = new SourcingTest\EventStubForTestingOptionalParameterOnHandlingMethod(); - $event = Event\Envelope::new($event, $this->id1, 1); - $sourcing = new SourcingTest\EventSourcedAggregateRootStub($this->id1); - - $exception = new Domain\Event\Exception\NoEventApplyingMethodFound($sourcing, $event); - $this->expectExceptionObject($exception); - - $sourcing->replay(new InMemoryStream($event)); - } - - public function testApplyingMethodPresentForEventsParentClassOnly(): void - { - $event1 = new SourcingTest\EventWhichIsSubclassOfEvent7(); - $event1 = Event\Envelope::new($event1, $this->id1, 1); - $event2 = new SourcingTest\AnotherEventWhichIsSubclassOfEvent7(); - $event2 = Event\Envelope::new($event2, $this->id1, 2); - - $sourcing = new SourcingTest\EventSourcedAggregateRootStub($this->id1); - - self::assertEquals(0, $sourcing->numberOfAppliesOfEvent7()); - - $sourcing->replay(new InMemoryStream($event1, $event2)); - - self::assertEquals(2, $sourcing->numberOfAppliesOfEvent7()); - self::assertSame($event2, $sourcing->lastReplayed()); - self::assertEquals($event2, $sourcing->lastEvent()); - self::assertEquals(2, $sourcing->version()); - self::assertEmpty($sourcing->events()); - } - -// public function testApplyingMethodPresentForEventsParentClassAndOnlyOneOfChildren() -// { -// $this->id -// ->expects(self::exactly(2)) -// ->method('equals') -// ->willReturn(true) -// ; -// -// $event1 = new SourcingTest\EventWhichIsSubclassOfEvent8($this->id); -// $event2 = new SourcingTest\AnotherEventWhichIsSubclassOfEvent8($this->id); -// -// $sourcing = new SourcingTest\EventSourcedAggregateRootStub($this->id); -// -// self::assertFalse($sourcing->isEvent8Applied()); -// self::assertFalse($sourcing->isEvent8aApplied()); -// -// $sourcing->replay($event1, $event2); -// -// self::assertTrue($sourcing->isEvent8Applied()); -// self::assertTrue($sourcing->isEvent8aApplied()); -// self::assertSame($event2, $sourcing->lastReplayed()); -// self::assertEmpty($sourcing->events()); -// } - - public function testApplyingEventViaCommand(): void - { - $sourcing = new SourcingTest\EventSourcedAggregateRootStub($this->id1); - self::assertEmpty($sourcing->events()); - self::assertNull($sourcing->lastEvent()); - - self::assertFalse($sourcing->isEvent9Applied()); - - $sourcing->command1($this->id1); - - self::assertTrue($sourcing->isEvent9Applied()); - - $event = new SourcingTest\EventStubForTestingApplyingViaCommand(); - - self::assertNull($sourcing->lastReplayed()); - self::assertEquals($event, $sourcing->lastEvent()->message()); - self::assertEquals(0, $sourcing->version()); - self::assertEquals([$event], $sourcing->events()); - - $sourcing->commit(); - - self::assertNull($sourcing->lastReplayed()); - self::assertEquals($event, $sourcing->lastEvent()->message()); - self::assertEquals(1, $sourcing->version()); - self::assertEquals([], $sourcing->events()); - } - - public function testApplyingEventViaCommandResultingInAnException(): void - { - $sourcing = new SourcingTest\EventSourcedAggregateRootStub($this->id1); - - try { - self::assertEmpty($sourcing->events()); - self::assertNull($sourcing->lastEvent()); - self::assertNull($sourcing->lastReplayed()); - - $sourcing->command2($this->id1); - - self::fail(); - } catch (\Exception $thrown) { - self::assertEquals(new \Exception('Command resulting in an exception'), $thrown); - self::assertEmpty($sourcing->events()); - self::assertNull($sourcing->lastEvent()); - self::assertNull($sourcing->lastReplayed()); - } - } - - public function testEventSourcingNonConsumer(): void - { - $sourcing = new Domain\Event\SourcingTest\EventSourcedNonConsumer($this->id1); - - $exception = new Domain\Event\Exception\SourcingObjectWithEventFailed($sourcing, $this->event1); - $this->expectExceptionObject($exception); - - $sourcing->replay(new InMemoryStream($this->event1)); - } - - public function testEventAndConsumerMismatch(): void - { - $sourcing = new SourcingTest\EventSourcedAggregateRootStub($this->id1); - - $exception = new Domain\Exception\EventAndConsumerMismatch($sourcing, $this->event2); - $this->expectExceptionObject($exception); - - $sourcing->replay(new InMemoryStream($this->event2)); - } -} - -namespace Streak\Domain\Event\SourcingTest; - -use Streak\Domain; -use Streak\Domain\AggregateRoot; -use Streak\Domain\Event; - -class EventSourcedAggregateRootStub implements Event\Consumer -{ - use Event\Sourcing; - - private \Streak\Domain\Id $id; - - private bool $eventStubForTestingPublicHandlingMethodApplied = false; - private bool $eventStubForTestingNonPublicHandlingMethodApplied = false; - private int $numberOfAppliesOfEvent7 = 0; - private bool $event8Applied = false; - private bool $event8aApplied = false; - private bool $event9Applied = false; - - public function __construct(AggregateRoot\Id $id) - { - $this->id = $id; - } - - public function producerId(): Domain\Id - { - return $this->id; - } - - public function applyEventStubForTestingPublicHandlingMethodApplied(EventStubForTestingPublicHandlingMethod $event): void - { - $this->eventStubForTestingPublicHandlingMethodApplied = true; - } - - public function applyEvent2(EventStubForTestingTwoOrMoreHandlingMethodsPresent $event2): void - { - } - - public function applyEvent2Deux(EventStubForTestingTwoOrMoreHandlingMethodsPresent $event2): void - { - } - - public function applyEvent4(EventStubForTestingTwoOrMoreParametersPresentOnHandlingMethod $event, mixed $thisParameterUnneeded): void - { - } - - public function applyEvent5(EventStubForTestingOptionalParameterOnHandlingMethod $optionalEventIsInvalid = null): void - { - } - - public function command1(AggregateRoot\Id $id): void - { - $this->apply(new EventStubForTestingApplyingViaCommand()); - } - - public function command2(AggregateRoot\Id $id): void - { - $this->apply(new EventStubForTestingApplyingViaCommandResultingInException()); - } - - public function isEventStubForTestingPublicHandlingMethodApplied(): bool - { - return $this->eventStubForTestingPublicHandlingMethodApplied; - } - - public function isEventStubForTestingNonPublicHandlingMethodApplied(): bool - { - return $this->eventStubForTestingNonPublicHandlingMethodApplied; - } - - public function isEvent8Applied(): bool - { - return $this->event8Applied; - } - - public function isEvent8aApplied(): bool - { - return $this->event8aApplied; - } - - public function isEvent9Applied(): bool - { - return $this->event9Applied; - } - - public function numberOfAppliesOfEvent7(): int - { - return $this->numberOfAppliesOfEvent7; - } - - public function id(): Domain\Id - { - return $this->id; - } - - private function applyEventStubForTestingNonPublicHandlingMethodApplied(EventStubForTestingNonPublicHandlingMethod $event): void - { - $this->eventStubForTestingNonPublicHandlingMethodApplied = true; - } - - private function applyEvent7(Event7 $event): void - { - ++$this->numberOfAppliesOfEvent7; - } - - private function applyEvent8(Event8 $event): void - { - $this->event8Applied = true; - } - - private function applyEvent8a(EventWhichIsSubclassOfEvent8 $event): void - { - $this->event8aApplied = true; - } - - private function applyEvent9(EventStubForTestingApplyingViaCommand $event): void - { - $this->event9Applied = true; - } - - private function applyEvent10(EventStubForTestingApplyingViaCommandResultingInException $event): void - { - throw new \Exception('Command resulting in an exception'); - } - - private function applyNonEvent(\stdClass $parameter): void - { - } - - private function applySomethingElse($parameters): void - { - } -} - -class EventStubForTestingPublicHandlingMethod implements Event -{ -} -class EventStubForTestingMismatching implements Event -{ -} -class EventStubForTestingTwoOrMoreHandlingMethodsPresent implements Event -{ -} -class EventStubForTestingMissingHandlingMethod implements Event -{ -} -class EventStubForTestingTwoOrMoreParametersPresentOnHandlingMethod implements Event -{ -} -class EventStubForTestingOptionalParameterOnHandlingMethod implements Event -{ -} -class EventStubForTestingNonPublicHandlingMethod implements Event -{ -} -class Event7 implements Event -{ -} -class EventWhichIsSubclassOfEvent7 extends Event7 -{ -} -class AnotherEventWhichIsSubclassOfEvent7 extends Event7 -{ -} -class Event8 implements Event -{ -} -class EventWhichIsSubclassOfEvent8 extends Event8 -{ -} -class AnotherEventWhichIsSubclassOfEvent8 extends Event8 -{ -} -class EventStubForTestingApplyingViaCommand implements Event -{ -} -class EventStubForTestingApplyingViaCommandResultingInException implements Event -{ -} - -class EventSourcedNonConsumer -{ - use Event\Sourcing; - - private \Streak\Domain\Id $id; - - public function __construct(AggregateRoot\Id $id) - { - $this->id = $id; - } - - public function producerId(): Domain\Id - { - return $this->id; - } -} diff --git a/tests/Domain/Event/Subscription/Exception/SubscriptionAlreadyCompletedTest.php b/tests/Domain/Event/Subscription/Exception/SubscriptionAlreadyCompletedTest.php index 12941a09..f443d792 100644 --- a/tests/Domain/Event/Subscription/Exception/SubscriptionAlreadyCompletedTest.php +++ b/tests/Domain/Event/Subscription/Exception/SubscriptionAlreadyCompletedTest.php @@ -38,7 +38,7 @@ public function testException(): void { $this->subscription ->expects(self::atLeastOnce()) - ->method('subscriptionId') + ->method('id') ->willReturn($this->subscriptionId) ; diff --git a/tests/Domain/Event/Subscription/Exception/SubscriptionAlreadyStartedTest.php b/tests/Domain/Event/Subscription/Exception/SubscriptionAlreadyStartedTest.php index 7a3b953f..d9bf47a5 100644 --- a/tests/Domain/Event/Subscription/Exception/SubscriptionAlreadyStartedTest.php +++ b/tests/Domain/Event/Subscription/Exception/SubscriptionAlreadyStartedTest.php @@ -38,7 +38,7 @@ public function testException(): void { $this->subscription ->expects(self::atLeastOnce()) - ->method('subscriptionId') + ->method('id') ->willReturn($this->subscriptionId) ; diff --git a/tests/Domain/Event/Subscription/Exception/SubscriptionNotStartedYetTest.php b/tests/Domain/Event/Subscription/Exception/SubscriptionNotStartedYetTest.php index ac4a6305..96b90af6 100644 --- a/tests/Domain/Event/Subscription/Exception/SubscriptionNotStartedYetTest.php +++ b/tests/Domain/Event/Subscription/Exception/SubscriptionNotStartedYetTest.php @@ -38,7 +38,7 @@ public function testException(): void { $this->subscription ->expects(self::atLeastOnce()) - ->method('subscriptionId') + ->method('id') ->willReturn($this->subscriptionId) ; diff --git a/tests/Domain/Event/Subscription/Exception/SubscriptionPausedTest.php b/tests/Domain/Event/Subscription/Exception/SubscriptionPausedTest.php index abeef08e..e10217ca 100644 --- a/tests/Domain/Event/Subscription/Exception/SubscriptionPausedTest.php +++ b/tests/Domain/Event/Subscription/Exception/SubscriptionPausedTest.php @@ -37,7 +37,7 @@ public function testException(): void { $this->subscription ->expects(self::atLeastOnce()) - ->method('subscriptionId') + ->method('id') ->willReturn($this->subscriptionId) ; diff --git a/tests/Domain/Event/Subscription/Exception/SubscriptionRestartNotPossibleTest.php b/tests/Domain/Event/Subscription/Exception/SubscriptionRestartNotPossibleTest.php index 46ab94d1..d8a86f31 100644 --- a/tests/Domain/Event/Subscription/Exception/SubscriptionRestartNotPossibleTest.php +++ b/tests/Domain/Event/Subscription/Exception/SubscriptionRestartNotPossibleTest.php @@ -38,7 +38,7 @@ public function testException(): void { $this->subscription ->expects(self::atLeastOnce()) - ->method('subscriptionId') + ->method('id') ->willReturn($this->subscriptionId) ; diff --git a/tests/Domain/Event/Sourced/Subscription/Repository/FilterTest.php b/tests/Domain/Event/Subscription/Repository/FilterTest.php similarity index 94% rename from tests/Domain/Event/Sourced/Subscription/Repository/FilterTest.php rename to tests/Domain/Event/Subscription/Repository/FilterTest.php index 3d770f52..68db7241 100644 --- a/tests/Domain/Event/Sourced/Subscription/Repository/FilterTest.php +++ b/tests/Domain/Event/Subscription/Repository/FilterTest.php @@ -11,10 +11,9 @@ declare(strict_types=1); -namespace Streak\Domain\Event\Sourced\Subscription\Repository; +namespace Streak\Domain\Event\Subscription\Repository; use PHPUnit\Framework\TestCase; -use Streak\Domain\Event\Subscription\Repository\Filter; /** * @author Alan Gabriel Bem diff --git a/tests/Domain/EventSourcingTest.php b/tests/Domain/EventSourcingTest.php new file mode 100644 index 00000000..85ac0bd0 --- /dev/null +++ b/tests/Domain/EventSourcingTest.php @@ -0,0 +1,748 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace Streak\Domain; + +use PHPUnit\Framework\TestCase; +use Streak\Domain\EventSourcingTest\EventSourcedAggregateRootStub; +use Streak\Domain\EventSourcingTest\EventSourcedAggregateRootStubId; +use Streak\Domain\EventSourcingTest\EventSourcedAggregateStub; +use Streak\Domain\EventSourcingTest\EventSourcedAggregateStubId; +use Streak\Domain\EventSourcingTest\EventSourcedEntityStub; +use Streak\Domain\EventSourcingTest\EventSourcedEntityStubId; +use Streak\Domain\Exception\EventMismatched; +use Streak\Infrastructure\Domain\Event\InMemoryStream; + +/** + * @author Alan Gabriel Bem + * + * @covers \Streak\Domain\AggregateRoot\EventSourcing + * @covers \Streak\Domain\Aggregate\EventSourcing + * @covers \Streak\Domain\Entity\EventSourcing + */ +class EventSourcingTest extends TestCase +{ + public function testSuccessfullyApplyingEventOnAggregateRoot(): void + { + $aggregateRootId1 = new EventSourcedAggregateRootStubId('f5e65690-e50d-4312-a175-b004ec1bd42a'); + $aggregateRoot1 = new EventSourcedAggregateRootStub($aggregateRootId1); + + $event = new EventSourcingTest\Event1(); + + self::assertNull($aggregateRoot1->lastEvent()); + self::assertSame(0, $aggregateRoot1->version()); + self::assertEmpty($aggregateRoot1->events()); + self::assertEmpty($aggregateRoot1->appliedEvents()); + + $aggregateRoot1->command($event); + + self::assertEquals($event, $aggregateRoot1->lastEvent()); + self::assertSame(0, $aggregateRoot1->version()); + self::assertEquals([$event], $aggregateRoot1->events()); + self::assertEquals([$event], $aggregateRoot1->appliedEvents()); + + $stream = $aggregateRoot1->events(); + + $aggregateRoot1->commit(); + + self::assertEquals($event, $aggregateRoot1->lastEvent()); + self::assertSame(1, $aggregateRoot1->version()); + self::assertEmpty($aggregateRoot1->events()); + self::assertEquals([$event], $aggregateRoot1->appliedEvents()); + + $freshAggregateRoot1 = new EventSourcedAggregateRootStub($aggregateRootId1); + $freshAggregateRoot1->replay(new InMemoryStream(...$stream)); + + self::assertNotSame($aggregateRoot1, $freshAggregateRoot1); + self::assertEquals($aggregateRoot1, $freshAggregateRoot1); + } + + public function testSuccessfullyApplyingEventOnAggregateRootButNotAggregate(): void + { + $aggregate1 = new EventSourcedAggregateStub(new EventSourcedAggregateStubId('51b37ad0-9e18-47fb-89ba-8d860472c852')); + $aggregateRoot1 = new EventSourcedAggregateRootStub(new EventSourcedAggregateRootStubId('f5e65690-e50d-4312-a175-b004ec1bd42a'), $aggregate1); + $aggregate1->registerAggregateRoot($aggregateRoot1); + + $event = new EventSourcingTest\Event1(); + + self::assertNull($aggregateRoot1->lastEvent()); + self::assertSame(0, $aggregateRoot1->version()); + self::assertEmpty($aggregateRoot1->events()); + self::assertEmpty($aggregateRoot1->appliedEvents()); + self::assertEmpty($aggregate1->appliedEvents()); + + $aggregateRoot1->command($event); + + self::assertEquals($event, $aggregateRoot1->lastEvent()); + self::assertSame(0, $aggregateRoot1->version()); + self::assertEquals([$event], $aggregateRoot1->events()); + self::assertEquals([$event], $aggregateRoot1->appliedEvents()); + self::assertEmpty($aggregate1->appliedEvents()); + + $stream = $aggregateRoot1->events(); + + $aggregateRoot1->commit(); + + self::assertEquals($event, $aggregateRoot1->lastEvent()); + self::assertSame(1, $aggregateRoot1->version()); + self::assertEmpty($aggregateRoot1->events()); + self::assertEquals([$event], $aggregateRoot1->appliedEvents()); + self::assertEmpty($aggregate1->appliedEvents()); + + $freshAggregate1 = new EventSourcedAggregateStub(new EventSourcedAggregateStubId('51b37ad0-9e18-47fb-89ba-8d860472c852')); + $freshAggregateRoot1 = new EventSourcedAggregateRootStub(new EventSourcedAggregateRootStubId('f5e65690-e50d-4312-a175-b004ec1bd42a'), $freshAggregate1); + $freshAggregate1->registerAggregateRoot($freshAggregateRoot1); + + $freshAggregateRoot1->replay(new InMemoryStream(...$stream)); + + self::assertNotSame($aggregateRoot1, $freshAggregateRoot1); + self::assertEquals($aggregateRoot1, $freshAggregateRoot1); + } + + public function testSuccessfullyApplyingEventOnAggregateRootButNotAggregateAndEntity(): void + { + $entity1 = new EventSourcedEntityStub(new EventSourcedEntityStubId('bafbcfd1-0355-42b4-bd3f-0a5379570574')); + $aggregate1 = new EventSourcedAggregateStub(new EventSourcedAggregateStubId('51b37ad0-9e18-47fb-89ba-8d860472c852'), $entity1); + $aggregateRoot1 = new EventSourcedAggregateRootStub(new EventSourcedAggregateRootStubId('f5e65690-e50d-4312-a175-b004ec1bd42a'), $aggregate1); + $aggregate1->registerAggregateRoot($aggregateRoot1); + $entity1->registerAggregate($aggregate1); + + $event = new EventSourcingTest\Event1(); + + self::assertNull($aggregateRoot1->lastEvent()); + self::assertSame(0, $aggregateRoot1->version()); + self::assertEmpty($aggregateRoot1->events()); + self::assertEmpty($aggregateRoot1->appliedEvents()); + self::assertEmpty($aggregate1->appliedEvents()); + self::assertEmpty($entity1->appliedEvents()); + + $aggregateRoot1->command($event); + + self::assertEquals($event, $aggregateRoot1->lastEvent()); + self::assertSame(0, $aggregateRoot1->version()); + self::assertEquals([$event], $aggregateRoot1->events()); + self::assertEquals([$event], $aggregateRoot1->appliedEvents()); + self::assertEmpty($aggregate1->appliedEvents()); + self::assertEmpty($entity1->appliedEvents()); + + $stream = $aggregateRoot1->events(); + + $aggregateRoot1->commit(); + + self::assertEquals($event, $aggregateRoot1->lastEvent()); + self::assertSame(1, $aggregateRoot1->version()); + self::assertEmpty($aggregateRoot1->events()); + self::assertEquals([$event], $aggregateRoot1->appliedEvents()); + self::assertEmpty($aggregate1->appliedEvents()); + self::assertEmpty($entity1->appliedEvents()); + + $freshEntity1 = new EventSourcedEntityStub(new EventSourcedEntityStubId('bafbcfd1-0355-42b4-bd3f-0a5379570574')); + $freshAggregate1 = new EventSourcedAggregateStub(new EventSourcedAggregateStubId('51b37ad0-9e18-47fb-89ba-8d860472c852'), $freshEntity1); + $freshAggregateRoot1 = new EventSourcedAggregateRootStub(new EventSourcedAggregateRootStubId('f5e65690-e50d-4312-a175-b004ec1bd42a'), $freshAggregate1); + $freshAggregate1->registerAggregateRoot($freshAggregateRoot1); + $freshEntity1->registerAggregate($freshAggregate1); + + $freshAggregateRoot1->replay(new InMemoryStream(...$stream)); + + self::assertNotSame($aggregateRoot1, $freshAggregateRoot1); + self::assertEquals($aggregateRoot1, $freshAggregateRoot1); + } + + public function testSuccessfullyApplyingEventOnAggregateAndAggregateRoot(): void + { + $aggregate1 = new EventSourcedAggregateStub(new EventSourcedAggregateStubId('51b37ad0-9e18-47fb-89ba-8d860472c852')); + $aggregateRoot1 = new EventSourcedAggregateRootStub(new EventSourcedAggregateRootStubId('f5e65690-e50d-4312-a175-b004ec1bd42a'), $aggregate1); + $aggregate1->registerAggregateRoot($aggregateRoot1); + + $event = new EventSourcingTest\Event1(); + + self::assertNull($aggregateRoot1->lastEvent()); + self::assertSame(0, $aggregateRoot1->version()); + self::assertEmpty($aggregateRoot1->events()); + self::assertEmpty($aggregateRoot1->appliedEvents()); + self::assertEmpty($aggregate1->appliedEvents()); + + $aggregateRoot1->commandOnAggregate1($event); + + self::assertEquals($event, $aggregateRoot1->lastEvent()); + self::assertSame(0, $aggregateRoot1->version()); + self::assertEquals([$event], $aggregateRoot1->events()); + self::assertEquals([$event], $aggregateRoot1->appliedEvents()); + self::assertEquals([$event], $aggregate1->appliedEvents()); + + $stream = $aggregateRoot1->events(); + + $aggregateRoot1->commit(); + + self::assertEquals($event, $aggregateRoot1->lastEvent()); + self::assertSame(1, $aggregateRoot1->version()); + self::assertEmpty($aggregateRoot1->events()); + self::assertEquals([$event], $aggregateRoot1->appliedEvents()); + self::assertEquals([$event], $aggregate1->appliedEvents()); + + $freshAggregate1 = new EventSourcedAggregateStub(new EventSourcedAggregateStubId('51b37ad0-9e18-47fb-89ba-8d860472c852')); + $freshAggregateRoot1 = new EventSourcedAggregateRootStub(new EventSourcedAggregateRootStubId('f5e65690-e50d-4312-a175-b004ec1bd42a'), $freshAggregate1); + $freshAggregate1->registerAggregateRoot($freshAggregateRoot1); + + $freshAggregateRoot1->replay(new InMemoryStream(...$stream)); + + self::assertNotSame($aggregateRoot1, $freshAggregateRoot1); + self::assertEquals($aggregateRoot1, $freshAggregateRoot1); + } + + public function testSuccessfullyApplyingEventOnAggregateAndAggregateRootButNotEntity(): void + { + $entity1 = new EventSourcedEntityStub(new EventSourcedEntityStubId('bafbcfd1-0355-42b4-bd3f-0a5379570574')); + $aggregate1 = new EventSourcedAggregateStub(new EventSourcedAggregateStubId('51b37ad0-9e18-47fb-89ba-8d860472c852'), $entity1); + $aggregateRoot1 = new EventSourcedAggregateRootStub(new EventSourcedAggregateRootStubId('f5e65690-e50d-4312-a175-b004ec1bd42a'), $aggregate1); + $aggregate1->registerAggregateRoot($aggregateRoot1); + $entity1->registerAggregate($aggregate1); + + $event = new EventSourcingTest\Event1(); + + self::assertNull($aggregateRoot1->lastEvent()); + self::assertSame(0, $aggregateRoot1->version()); + self::assertEmpty($aggregateRoot1->events()); + self::assertEmpty($aggregateRoot1->appliedEvents()); + self::assertEmpty($aggregate1->appliedEvents()); + self::assertEmpty($entity1->appliedEvents()); + + $aggregateRoot1->commandOnAggregate1($event); + + self::assertEquals($event, $aggregateRoot1->lastEvent()); + self::assertSame(0, $aggregateRoot1->version()); + self::assertEquals([$event], $aggregateRoot1->events()); + self::assertEquals([$event], $aggregateRoot1->appliedEvents()); + self::assertEquals([$event], $aggregate1->appliedEvents()); + self::assertEmpty($entity1->appliedEvents()); + + $stream = $aggregateRoot1->events(); + + $aggregateRoot1->commit(); + + self::assertEquals($event, $aggregateRoot1->lastEvent()); + self::assertSame(1, $aggregateRoot1->version()); + self::assertEmpty($aggregateRoot1->events()); + self::assertEquals([$event], $aggregateRoot1->appliedEvents()); + self::assertEquals([$event], $aggregate1->appliedEvents()); + self::assertEmpty($entity1->appliedEvents()); + + $freshEntity1 = new EventSourcedEntityStub(new EventSourcedEntityStubId('bafbcfd1-0355-42b4-bd3f-0a5379570574')); + $freshAggregate1 = new EventSourcedAggregateStub(new EventSourcedAggregateStubId('51b37ad0-9e18-47fb-89ba-8d860472c852'), $freshEntity1); + $freshAggregateRoot1 = new EventSourcedAggregateRootStub(new EventSourcedAggregateRootStubId('f5e65690-e50d-4312-a175-b004ec1bd42a'), $freshAggregate1); + $freshAggregate1->registerAggregateRoot($freshAggregateRoot1); + $freshEntity1->registerAggregate($freshAggregate1); + + $freshAggregateRoot1->replay(new InMemoryStream(...$stream)); + + self::assertNotSame($aggregateRoot1, $freshAggregateRoot1); + self::assertEquals($aggregateRoot1, $freshAggregateRoot1); + } + + public function testSuccessfullyApplyingEventOnAggregateButNotAggregateRoot(): void + { + $aggregate1 = new EventSourcedAggregateStub(new EventSourcedAggregateStubId('51b37ad0-9e18-47fb-89ba-8d860472c852')); + $aggregateRoot1 = new EventSourcedAggregateRootStub(new EventSourcedAggregateRootStubId('f5e65690-e50d-4312-a175-b004ec1bd42a'), $aggregate1); + $aggregate1->registerAggregateRoot($aggregateRoot1); + + $event = new EventSourcingTest\Event2(); + + self::assertNull($aggregateRoot1->lastEvent()); + self::assertSame(0, $aggregateRoot1->version()); + self::assertEmpty($aggregateRoot1->events()); + self::assertEmpty($aggregateRoot1->appliedEvents()); + self::assertEmpty($aggregate1->appliedEvents()); + + $aggregateRoot1->commandOnAggregate1($event); + + self::assertEquals($event, $aggregateRoot1->lastEvent()); + self::assertSame(0, $aggregateRoot1->version()); + self::assertEquals([$event], $aggregateRoot1->events()); + self::assertEmpty($aggregateRoot1->appliedEvents()); + self::assertEquals([$event], $aggregate1->appliedEvents()); + + $stream = $aggregateRoot1->events(); + + $aggregateRoot1->commit(); + + self::assertEquals($event, $aggregateRoot1->lastEvent()); + self::assertSame(1, $aggregateRoot1->version()); + self::assertEmpty($aggregateRoot1->events()); + self::assertEmpty($aggregateRoot1->appliedEvents()); + self::assertEquals([$event], $aggregate1->appliedEvents()); + + $freshAggregate1 = new EventSourcedAggregateStub(new EventSourcedAggregateStubId('51b37ad0-9e18-47fb-89ba-8d860472c852')); + $freshAggregateRoot1 = new EventSourcedAggregateRootStub(new EventSourcedAggregateRootStubId('f5e65690-e50d-4312-a175-b004ec1bd42a'), $freshAggregate1); + $freshAggregate1->registerAggregateRoot($freshAggregateRoot1); + + $freshAggregateRoot1->replay(new InMemoryStream(...$stream)); + + self::assertNotSame($aggregateRoot1, $freshAggregateRoot1); + self::assertEquals($aggregateRoot1, $freshAggregateRoot1); + } + + public function testSuccessfullyApplyingEventOnEntityAndAggregateAndAggregateRoot(): void + { + $entity1 = new EventSourcedEntityStub(new EventSourcedEntityStubId('bafbcfd1-0355-42b4-bd3f-0a5379570574')); + $aggregate1 = new EventSourcedAggregateStub(new EventSourcedAggregateStubId('51b37ad0-9e18-47fb-89ba-8d860472c852'), $entity1); + $aggregateRoot1 = new EventSourcedAggregateRootStub(new EventSourcedAggregateRootStubId('f5e65690-e50d-4312-a175-b004ec1bd42a'), $aggregate1); + $aggregate1->registerAggregateRoot($aggregateRoot1); + $entity1->registerAggregate($aggregate1); + + $event = new EventSourcingTest\Event1(); + + self::assertNull($aggregateRoot1->lastEvent()); + self::assertSame(0, $aggregateRoot1->version()); + self::assertEmpty($aggregateRoot1->events()); + self::assertEmpty($aggregateRoot1->appliedEvents()); + self::assertEmpty($aggregate1->appliedEvents()); + self::assertEmpty($entity1->appliedEvents()); + + $aggregateRoot1->commandOnEntity1OfAggregate1($event); + + self::assertEquals($event, $aggregateRoot1->lastEvent()); + self::assertSame(0, $aggregateRoot1->version()); + self::assertEquals([$event], $aggregateRoot1->events()); + self::assertEquals([$event], $aggregateRoot1->appliedEvents()); + self::assertEquals([$event], $aggregate1->appliedEvents()); + self::assertEquals([$event], $entity1->appliedEvents()); + + $stream = $aggregateRoot1->events(); + + $aggregateRoot1->commit(); + + self::assertEquals($event, $aggregateRoot1->lastEvent()); + self::assertSame(1, $aggregateRoot1->version()); + self::assertEmpty($aggregateRoot1->events()); + self::assertEquals([$event], $aggregateRoot1->appliedEvents()); + self::assertEquals([$event], $aggregate1->appliedEvents()); + self::assertEquals([$event], $entity1->appliedEvents()); + + $freshEntity1 = new EventSourcedEntityStub(new EventSourcedEntityStubId('bafbcfd1-0355-42b4-bd3f-0a5379570574')); + $freshAggregate1 = new EventSourcedAggregateStub(new EventSourcedAggregateStubId('51b37ad0-9e18-47fb-89ba-8d860472c852'), $freshEntity1); + $freshAggregateRoot1 = new EventSourcedAggregateRootStub(new EventSourcedAggregateRootStubId('f5e65690-e50d-4312-a175-b004ec1bd42a'), $freshAggregate1); + $freshAggregate1->registerAggregateRoot($freshAggregateRoot1); + $freshEntity1->registerAggregate($freshAggregate1); + + $freshAggregateRoot1->replay(new InMemoryStream(...$stream)); + + self::assertNotSame($aggregateRoot1, $freshAggregateRoot1); + self::assertEquals($aggregateRoot1, $freshAggregateRoot1); + } + + public function testSuccessfullyApplyingEventOnEntityAndAggregateButNotAggregateRoot(): void + { + $entity1 = new EventSourcedEntityStub(new EventSourcedEntityStubId('bafbcfd1-0355-42b4-bd3f-0a5379570574')); + $aggregate1 = new EventSourcedAggregateStub(new EventSourcedAggregateStubId('51b37ad0-9e18-47fb-89ba-8d860472c852'), $entity1); + $aggregateRoot1 = new EventSourcedAggregateRootStub(new EventSourcedAggregateRootStubId('f5e65690-e50d-4312-a175-b004ec1bd42a'), $aggregate1); + $aggregate1->registerAggregateRoot($aggregateRoot1); + $entity1->registerAggregate($aggregate1); + + $event = new EventSourcingTest\Event2(); + + self::assertNull($aggregateRoot1->lastEvent()); + self::assertSame(0, $aggregateRoot1->version()); + self::assertEmpty($aggregateRoot1->events()); + self::assertEmpty($aggregateRoot1->appliedEvents()); + self::assertEmpty($aggregate1->appliedEvents()); + self::assertEmpty($entity1->appliedEvents()); + + $aggregateRoot1->commandOnEntity1OfAggregate1($event); + + self::assertEquals($event, $aggregateRoot1->lastEvent()); + self::assertSame(0, $aggregateRoot1->version()); + self::assertEquals([$event], $aggregateRoot1->events()); + self::assertEmpty($aggregateRoot1->appliedEvents()); + self::assertEquals([$event], $aggregate1->appliedEvents()); + self::assertEquals([$event], $entity1->appliedEvents()); + + $stream = $aggregateRoot1->events(); + + $aggregateRoot1->commit(); + + self::assertEquals($event, $aggregateRoot1->lastEvent()); + self::assertSame(1, $aggregateRoot1->version()); + self::assertEmpty($aggregateRoot1->events()); + self::assertEmpty($aggregateRoot1->appliedEvents()); + self::assertEquals([$event], $aggregate1->appliedEvents()); + self::assertEquals([$event], $entity1->appliedEvents()); + + $freshEntity1 = new EventSourcedEntityStub(new EventSourcedEntityStubId('bafbcfd1-0355-42b4-bd3f-0a5379570574')); + $freshAggregate1 = new EventSourcedAggregateStub(new EventSourcedAggregateStubId('51b37ad0-9e18-47fb-89ba-8d860472c852'), $freshEntity1); + $freshAggregateRoot1 = new EventSourcedAggregateRootStub(new EventSourcedAggregateRootStubId('f5e65690-e50d-4312-a175-b004ec1bd42a'), $freshAggregate1); + $freshAggregate1->registerAggregateRoot($freshAggregateRoot1); + $freshEntity1->registerAggregate($freshAggregate1); + + $freshAggregateRoot1->replay(new InMemoryStream(...$stream)); + + self::assertNotSame($aggregateRoot1, $freshAggregateRoot1); + self::assertEquals($aggregateRoot1, $freshAggregateRoot1); + } + + public function testSuccessfullyApplyingEventOnEntityAndAggregateRootButNotAggregate(): void + { + $entity1 = new EventSourcedEntityStub(new EventSourcedEntityStubId('bafbcfd1-0355-42b4-bd3f-0a5379570574')); + $aggregate1 = new EventSourcedAggregateStub(new EventSourcedAggregateStubId('51b37ad0-9e18-47fb-89ba-8d860472c852'), $entity1); + $aggregateRoot1 = new EventSourcedAggregateRootStub(new EventSourcedAggregateRootStubId('f5e65690-e50d-4312-a175-b004ec1bd42a'), $aggregate1); + $aggregate1->registerAggregateRoot($aggregateRoot1); + $entity1->registerAggregate($aggregate1); + + $event = new EventSourcingTest\Event4(); + + self::assertNull($aggregateRoot1->lastEvent()); + self::assertSame(0, $aggregateRoot1->version()); + self::assertEmpty($aggregateRoot1->events()); + self::assertEmpty($aggregateRoot1->appliedEvents()); + self::assertEmpty($aggregate1->appliedEvents()); + self::assertEmpty($entity1->appliedEvents()); + + $aggregateRoot1->commandOnEntity1OfAggregate1($event); + + self::assertEquals($event, $aggregateRoot1->lastEvent()); + self::assertSame(0, $aggregateRoot1->version()); + self::assertEquals([$event], $aggregateRoot1->events()); + self::assertEquals([$event], $aggregateRoot1->appliedEvents()); + self::assertEmpty($aggregate1->appliedEvents()); + self::assertEquals([$event], $entity1->appliedEvents()); + + $stream = $aggregateRoot1->events(); + + $aggregateRoot1->commit(); + + self::assertEquals($event, $aggregateRoot1->lastEvent()); + self::assertSame(1, $aggregateRoot1->version()); + self::assertEmpty($aggregateRoot1->events()); + self::assertEquals([$event], $aggregateRoot1->appliedEvents()); + self::assertEmpty($aggregate1->appliedEvents()); + self::assertEquals([$event], $entity1->appliedEvents()); + + $freshEntity1 = new EventSourcedEntityStub(new EventSourcedEntityStubId('bafbcfd1-0355-42b4-bd3f-0a5379570574')); + $freshAggregate1 = new EventSourcedAggregateStub(new EventSourcedAggregateStubId('51b37ad0-9e18-47fb-89ba-8d860472c852'), $freshEntity1); + $freshAggregateRoot1 = new EventSourcedAggregateRootStub(new EventSourcedAggregateRootStubId('f5e65690-e50d-4312-a175-b004ec1bd42a'), $freshAggregate1); + $freshAggregate1->registerAggregateRoot($freshAggregateRoot1); + $freshEntity1->registerAggregate($freshAggregate1); + + $freshAggregateRoot1->replay(new InMemoryStream(...$stream)); + + self::assertNotSame($aggregateRoot1, $freshAggregateRoot1); + self::assertEquals($aggregateRoot1, $freshAggregateRoot1); + } + + public function testMismatchedEventOnAggregateRoot(): void + { + $entity1 = new EventSourcedEntityStub(new EventSourcedEntityStubId('bafbcfd1-0355-42b4-bd3f-0a5379570574')); + $aggregate1 = new EventSourcedAggregateStub(new EventSourcedAggregateStubId('51b37ad0-9e18-47fb-89ba-8d860472c852'), $entity1); + $aggregateRoot1 = new EventSourcedAggregateRootStub(new EventSourcedAggregateRootStubId('f5e65690-e50d-4312-a175-b004ec1bd42a'), $aggregate1); + $aggregate1->registerAggregateRoot($aggregateRoot1); + $entity1->registerAggregate($aggregate1); + + $event = new EventSourcingTest\Event4(); + $event = Event\Envelope::new($event, new EventSourcedAggregateStubId('61888494-fd58-412c-86c3-03cf81aca443'), 1); + + try { + $aggregateRoot1->applyEvent($event); + self::fail(); + } catch (EventMismatched $exception) { + self::assertSame($aggregateRoot1, $exception->object()); + self::assertSame($event, $exception->event()); + } + } + + public function testMismatchedEventOnAggregate(): void + { + $entity1 = new EventSourcedEntityStub(new EventSourcedEntityStubId('bafbcfd1-0355-42b4-bd3f-0a5379570574')); + $aggregate1 = new EventSourcedAggregateStub(new EventSourcedAggregateStubId('51b37ad0-9e18-47fb-89ba-8d860472c852'), $entity1); + $aggregateRoot1 = new EventSourcedAggregateRootStub(new EventSourcedAggregateRootStubId('f5e65690-e50d-4312-a175-b004ec1bd42a'), $aggregate1); + $aggregate1->registerAggregateRoot($aggregateRoot1); + $entity1->registerAggregate($aggregate1); + + $event = new EventSourcingTest\Event2(); + $event = Event\Envelope::new($event, new EventSourcedAggregateStubId('61888494-fd58-412c-86c3-03cf81aca443'), 1); + + try { + $aggregate1->applyEvent($event); + self::fail(); + } catch (EventMismatched $exception) { + self::assertSame($aggregate1, $exception->object()); + self::assertSame($event, $exception->event()); + } + } + + public function testMismatchedEventOnEntity(): void + { + $entity1 = new EventSourcedEntityStub(new EventSourcedEntityStubId('bafbcfd1-0355-42b4-bd3f-0a5379570574')); + $aggregate1 = new EventSourcedAggregateStub(new EventSourcedAggregateStubId('51b37ad0-9e18-47fb-89ba-8d860472c852'), $entity1); + $aggregateRoot1 = new EventSourcedAggregateRootStub(new EventSourcedAggregateRootStubId('f5e65690-e50d-4312-a175-b004ec1bd42a'), $aggregate1); + $aggregate1->registerAggregateRoot($aggregateRoot1); + $entity1->registerAggregate($aggregate1); + + $event = new EventSourcingTest\Event2(); + $event = Event\Envelope::new($event, new EventSourcedAggregateStubId('61888494-fd58-412c-86c3-03cf81aca443'), 1); + + try { + $entity1->applyEvent($event); + self::fail(); + } catch (EventMismatched $exception) { + self::assertSame($entity1, $exception->object()); + self::assertSame($event, $exception->event()); + } + } + + public function testRegisteringAggregateOnItself(): void + { + $this->expectExceptionObject(new \BadMethodCallException('You can\'t register aggregate on itself.')); + + $aggregate1 = new EventSourcedAggregateStub(new EventSourcedAggregateStubId('51b37ad0-9e18-47fb-89ba-8d860472c852')); + $aggregate1->registerAggregate($aggregate1); + } + + public function testObtainingAggregateRootOnAggregateWhenItsNotRegistered(): void + { + $this->expectExceptionObject(new \BadMethodCallException('Aggregate root no registered. Did you forget to run Streak\Domain\EventSourcingTest\EventSourcedAggregateStub::registerAggregateRoot()?')); + + $aggregate1 = new EventSourcedAggregateStub(new EventSourcedAggregateStubId('51b37ad0-9e18-47fb-89ba-8d860472c852')); + + $aggregate1->aggregateRoot(); + } + + public function testObtainingAggregateRootOnEntityWhenItsNotRegistered(): void + { + $this->expectExceptionObject(new \BadMethodCallException('Aggregate root no registered. Did you forget to run Streak\Domain\EventSourcingTest\EventSourcedEntityStub::registerAggregateRoot()?')); + + $entity1 = new EventSourcedEntityStub(new EventSourcedEntityStubId('bafbcfd1-0355-42b4-bd3f-0a5379570574')); + + $entity1->aggregateRoot(); + } +} + +namespace Streak\Domain\EventSourcingTest; + +use Streak\Domain; +use Streak\Domain\Aggregate; +use Streak\Domain\AggregateRoot; +use Streak\Domain\Entity; +use Streak\Domain\Event; + +class EventSourcedAggregateRootStubId extends Domain\Id\UUID implements AggregateRoot\Id +{ +} + +class EventSourcedAggregateRootStub implements Event\Sourced\AggregateRoot +{ + use AggregateRoot\Comparison; + use AggregateRoot\EventSourcing; + use AggregateRoot\Identification; + + private array $appliedEvents = []; + + public function __construct( + EventSourcedAggregateRootStubId $id, + private ?EventSourcedAggregateStub $aggregate1 = null, + private ?EventSourcedAggregateStub $aggregate2 = null, + private ?EventSourcedEntityStub $entity1 = null, + private ?EventSourcedEntityStub $entity2 = null, + ) { + $this->identifyBy($id); + } + + public function entity1(): ?Event\Sourced\Entity + { + return $this->entity1; + } + + public function entity2(): ?Event\Sourced\Entity + { + return $this->entity2; + } + + public function command(Event $event): void + { + $this->apply($event); + } + + public function commandOnAggregate1(Event $event): void + { + $this->aggregate1->commandOnAggregate($event); + } + + public function commandOnEntity1OfAggregate1(Event $event): void + { + $this->aggregate1->commandOnEntity1($event); + } + + public function commandOnEntity2OfAggregate1(Event $event): void + { + $this->aggregate1->commandOnEntity2($event); + } + + public function commandOnEntity1(Event $event): void + { + $this->entity1->command($event); + } + + public function commandOnAggregate2(Event $event): void + { + $this->aggregate2->commandOnAggregate($event); + } + + public function commandOnEntity1OfAggregate2(Event $event): void + { + $this->aggregate2->commandOnEntity1($event); + } + + public function commandOnEntity2OfAggregate2(Event $event): void + { + $this->aggregate2->commandOnEntity2($event); + } + + public function commandOnEntity2(Event $event): void + { + $this->entity1->command($event); + } + + public function appliedEvents(): array + { + return $this->appliedEvents; + } + + private function applyEvent1(Event1 $event): void + { + $this->appliedEvents = [$event]; + } + + private function applyEvent4(Event4 $event): void + { + $this->appliedEvents[] = $event; + } +} + +class EventSourcedAggregateStubId extends Domain\Id\UUID implements Aggregate\Id +{ +} + +class EventSourcedAggregateStub implements Event\Sourced\Aggregate +{ + use Aggregate\Comparison; + use Aggregate\EventSourcing; + use Aggregate\Identification; + + /** + * @var Event\Envelope[] + */ + private array $appliedEvents = []; + + public function __construct( + EventSourcedAggregateStubId $id, + private ?EventSourcedEntityStub $entity1 = null, + private ?EventSourcedEntityStub $entity2 = null, + ) { + $this->identifyBy($id); + } + + public function commandOnAggregate(Event $event): void + { + $this->apply($event); + } + + public function commandOnEntity1(Event $event): void + { + $this->entity1->command($event); + } + + public function commandOnEntity2(Event $event): void + { + $this->entity2->command($event); + } + + public function appliedEvents(): array + { + return $this->appliedEvents; + } + + private function applyEvent1(Event1 $event): void + { + $this->appliedEvents = [$event]; + } + + private function applyEvent2(Event2 $event): void + { + $this->appliedEvents = [$event]; + } +} + +class EventSourcedEntityStubId extends Domain\Id\UUID implements Entity\Id +{ +} + +class EventSourcedEntityStub implements Event\Sourced\Entity +{ + use Entity\Comparison; + use Entity\EventSourcing; + use Entity\Identification; + + /** + * @var Event\Envelope[] + */ + private array $appliedEvents = []; + + public function __construct(EventSourcedEntityStubId $id) + { + $this->identifyBy($id); + } + + public function command(Event $event): void + { + $this->apply($event); + } + + public function appliedEvents(): array + { + return $this->appliedEvents; + } + + private function applyEvent1(Event1 $event): void + { + $this->appliedEvents[] = $event; + } + + private function applyEvent2(Event2 $event): void + { + $this->appliedEvents[] = $event; + } + + private function applyEvent3(Event3 $event): void + { + $this->appliedEvents[] = $event; + } + + private function applyEvent4(Event4 $event): void + { + $this->appliedEvents[] = $event; + } +} + +class Event1 implements Event +{ +} + +class Event2 implements Event +{ +} + +class Event3 implements Event +{ +} + +class Event4 implements Event +{ +} diff --git a/tests/Domain/Exception/EventAndConsumerMismatchTest.php b/tests/Domain/Exception/EventMismatchedTest.php similarity index 66% rename from tests/Domain/Exception/EventAndConsumerMismatchTest.php rename to tests/Domain/Exception/EventMismatchedTest.php index 67da2ea5..0a873e82 100644 --- a/tests/Domain/Exception/EventAndConsumerMismatchTest.php +++ b/tests/Domain/Exception/EventMismatchedTest.php @@ -21,25 +21,25 @@ /** * @author Alan Gabriel Bem * - * @covers \Streak\Domain\Exception\EventAndConsumerMismatch + * @covers \Streak\Domain\Exception\EventMismatched */ -class EventAndConsumerMismatchTest extends TestCase +class EventMismatchedTest extends TestCase { - private Event\Consumer $consumer; + private Event\Sourced\Entity $entity; private Domain\Event\Envelope $event; protected function setUp(): void { - $this->consumer = $this->getMockBuilder(Event\Consumer::class)->getMockForAbstractClass(); + $this->entity = $this->getMockBuilder(Event\Sourced\Entity::class)->getMockForAbstractClass(); $this->event = Event\Envelope::new($this->getMockBuilder(Domain\Event::class)->getMockForAbstractClass(), UUID::random()); } public function testException(): void { - $exception = new EventAndConsumerMismatch($this->consumer, $this->event); + $exception = new EventMismatched($this->entity, $this->event); - self::assertSame($this->consumer, $exception->consumer()); + self::assertSame($this->entity, $exception->object()); self::assertSame($this->event, $exception->event()); } } diff --git a/tests/Infrastructure/Application/Sensor/CommittingSensorTest.php b/tests/Infrastructure/Application/Sensor/CommittingSensorTest.php index 9806bfea..884eefb1 100644 --- a/tests/Infrastructure/Application/Sensor/CommittingSensorTest.php +++ b/tests/Infrastructure/Application/Sensor/CommittingSensorTest.php @@ -49,21 +49,12 @@ public function testSensor(): void $this->sensor ->expects(self::once()) - ->method('sensorId') + ->method('id') ->with() ->willReturn($this->sensorId) ; - self::assertSame($this->sensorId, $sensor->sensorId()); - - $this->sensor - ->expects(self::once()) - ->method('producerId') - ->with() - ->willReturn($this->sensorId) - ; - - self::assertSame($this->sensorId, $sensor->producerId()); + self::assertSame($this->sensorId, $sensor->id()); $this->sensor ->expects(self::once()) diff --git a/tests/Infrastructure/Application/Sensor/LoggingSensorTest.php b/tests/Infrastructure/Application/Sensor/LoggingSensorTest.php index 55877581..937e1ad3 100644 --- a/tests/Infrastructure/Application/Sensor/LoggingSensorTest.php +++ b/tests/Infrastructure/Application/Sensor/LoggingSensorTest.php @@ -62,19 +62,11 @@ public function testObject(): void $this->sensor ->expects(self::once()) - ->method('sensorId') + ->method('id') ->willReturn($this->sensorId) ; - self::assertSame($this->sensorId, $sensor->sensorId()); - - $this->sensor - ->expects(self::once()) - ->method('producerId') - ->willReturn($this->sensorId) - ; - - self::assertSame($this->sensorId, $sensor->producerId()); + self::assertSame($this->sensorId, $sensor->id()); $this->sensor ->expects(self::once()) diff --git a/tests/Infrastructure/Domain/AggregateRoot/Repository/EventSourcedRepositoryTest.php b/tests/Infrastructure/Domain/AggregateRoot/Repository/EventSourcedRepositoryTest.php index bf63495d..4e8f1ad8 100644 --- a/tests/Infrastructure/Domain/AggregateRoot/Repository/EventSourcedRepositoryTest.php +++ b/tests/Infrastructure/Domain/AggregateRoot/Repository/EventSourcedRepositoryTest.php @@ -34,7 +34,7 @@ class EventSourcedRepositoryTest extends TestCase private Domain\AggregateRoot $nonEventSourcedAggregateRoot; private Event\Sourced\AggregateRoot $aggregateRoot; - private Event\Sourced\AggregateRoot\Id $aggregateRootId; + private Domain\AggregateRoot\Id $aggregateRootId; private Domain\Event\Envelope $event1; @@ -50,7 +50,7 @@ protected function setUp(): void $this->nonEventSourcedAggregateRoot = $this->getMockBuilder(Domain\AggregateRoot::class)->getMockForAbstractClass(); $this->aggregateRoot = $this->getMockBuilder(Event\Sourced\AggregateRoot::class)->getMockForAbstractClass(); - $this->aggregateRootId = $this->getMockBuilder(Event\Sourced\AggregateRoot\Id::class)->getMockForAbstractClass(); + $this->aggregateRootId = $this->getMockBuilder(Domain\AggregateRoot\Id::class)->getMockForAbstractClass(); $this->event1 = Event\Envelope::new($this->getMockBuilder(Domain\Event::class)->getMockForAbstractClass(), $this->aggregateRootId, 1); $this->stream = $this->getMockBuilder(Event\Stream::class)->getMockForAbstractClass(); diff --git a/tests/Infrastructure/Domain/AggregateRoot/Snapshotter/Storage/Exception/SnapshotNotFoundTest.php b/tests/Infrastructure/Domain/AggregateRoot/Snapshotter/Storage/Exception/SnapshotNotFoundTest.php index 180bd2f8..dffbb244 100644 --- a/tests/Infrastructure/Domain/AggregateRoot/Snapshotter/Storage/Exception/SnapshotNotFoundTest.php +++ b/tests/Infrastructure/Domain/AggregateRoot/Snapshotter/Storage/Exception/SnapshotNotFoundTest.php @@ -37,7 +37,7 @@ public function testException(): void { $this->aggregate ->expects(self::atLeastOnce()) - ->method('aggregateRootId') + ->method('id') ->willReturn($this->aggregateId) ; $this->aggregateId diff --git a/tests/Infrastructure/Domain/AggregateRoot/Snapshotter/Storage/PostgresStorageTest.php b/tests/Infrastructure/Domain/AggregateRoot/Snapshotter/Storage/PostgresStorageTest.php index 27549ce4..74393be6 100644 --- a/tests/Infrastructure/Domain/AggregateRoot/Snapshotter/Storage/PostgresStorageTest.php +++ b/tests/Infrastructure/Domain/AggregateRoot/Snapshotter/Storage/PostgresStorageTest.php @@ -115,20 +115,20 @@ public function testItFinds(): void ]); $snapshot = $this->storage->find($this->createAggregateRootStub($id)); - self::assertEquals('snapshot', $snapshot); + self::assertSame('snapshot', $snapshot); } public function testItDoesntFindWhenTableDoesNotExists(): void { $this->givenSnapshotsTableDoesNotExists(); - self::expectException(SnapshotNotFound::class); + $this->expectException(SnapshotNotFound::class); $this->storage->find($this->createAggregateRootStub('3e7c8ffa-6bc6-4070-a6b5-30f9ae1c06fe')); } public function testItDoesntFindWhenRowDoesNotExist(): void { $this->givenSnapshotsTableExists(); - self::expectException(SnapshotNotFound::class); + $this->expectException(SnapshotNotFound::class); $this->storage->find($this->createAggregateRootStub('3e7c8ffa-6bc6-4070-a6b5-30f9ae1c06fe')); } @@ -171,16 +171,13 @@ private function createAggregateRootStub(string $id): AggregateRoot class IdStub implements AggregateRoot\Id { - private string $id; - /** * IdMock constructor. * * @param $id */ - public function __construct(string $id) + public function __construct(private string $id) { - $this->id = $id; } public function equals(object $object): bool diff --git a/tests/Infrastructure/Domain/AggregateRoot/Snapshotter/Storage/TestCase.php b/tests/Infrastructure/Domain/AggregateRoot/Snapshotter/Storage/TestCase.php index 24bd051b..e429a434 100644 --- a/tests/Infrastructure/Domain/AggregateRoot/Snapshotter/Storage/TestCase.php +++ b/tests/Infrastructure/Domain/AggregateRoot/Snapshotter/Storage/TestCase.php @@ -38,11 +38,11 @@ protected function setUp(): void $this->aggregateId1 = new Storage\StorageTestCase\ExtendedUUID1('9bf583d5-d4ff-4cf3-bc53-8ffb6be0c67b'); $this->aggregate1 = $this->getMockBuilder(AggregateRoot::class)->setMockClassName('streak__aggregate_1')->getMockForAbstractClass(); - $this->aggregate1->method('aggregateRootId')->with()->willReturn($this->aggregateId1); + $this->aggregate1->method('id')->with()->willReturn($this->aggregateId1); $this->aggregateId2 = new Storage\StorageTestCase\ExtendedUUID2('d61546c6-cc51-4584-90f8-34203fd79b41'); $this->aggregate2 = $this->getMockBuilder(AggregateRoot::class)->setMockClassName('streak__aggregate_2')->getMockForAbstractClass(); - $this->aggregate2->method('aggregateRootId')->with()->willReturn($this->aggregateId2); + $this->aggregate2->method('id')->with()->willReturn($this->aggregateId2); } public function testObject(): void diff --git a/tests/Infrastructure/Domain/Event/Converter/NestedObjectConverterTest.php b/tests/Infrastructure/Domain/Event/Converter/NestedObjectConverterTest.php index 0582a35c..513fc2aa 100644 --- a/tests/Infrastructure/Domain/Event/Converter/NestedObjectConverterTest.php +++ b/tests/Infrastructure/Domain/Event/Converter/NestedObjectConverterTest.php @@ -177,7 +177,7 @@ public function testNestedArrayToObject(): void public function testItDoesntConvertWrongNestedType(): void { - self::expectException(Event\Exception\ConversionToArrayNotPossible::class); + $this->expectException(Event\Exception\ConversionToArrayNotPossible::class); $converter = new NestedObjectConverter(); $converter->objectToArray(new NestedResource(tmpfile())); } @@ -185,78 +185,37 @@ public function testItDoesntConvertWrongNestedType(): void class NestedResource { - /** - * @var resource - */ - private $resource; - /** * @param resource $resource */ - public function __construct($resource) + public function __construct(private $resource) { - $this->resource = $resource; } } class Event1Stub implements Event { - public string $publicStringProperty; - public int $publicIntegerProperty; - public float $publicFloatProperty; - public array $publicArrayProperty; - public $publicAnyTypeProperty; public array $publicEmptyArrayProperty; - protected string $protectedStringProperty; - protected int $protectedIntegerProperty; - protected float $protectedFloatProperty; - protected array $protectedArrayProperty; - protected $protectedAnyTypeProperty; protected array $protectedEmptyArrayProperty; - private string $privateStringProperty; - private int $privateIntegerProperty; - private float $privateFloatProperty; - private array $privateArrayProperty; - private $privateAnyTypeProperty; private array $privateEmptyArrayProperty; public function __construct( - string $privateStringProperty, - string $publicStringProperty, - string $protectedStringProperty, - int $privateIntegerProperty, - int $publicIntegerProperty, - int $protectedIntegerProperty, - float $privateFloatProperty, - float $publicFloatProperty, - float $protectedFloatProperty, - array $privateArrayProperty, - array $publicArrayProperty, - array $protectedArrayProperty, - $privateAnyTypeProperty, - $publicAnyTypeProperty, - $protectedAnyTypeProperty + private string $privateStringProperty, + public string $publicStringProperty, + protected string $protectedStringProperty, + private int $privateIntegerProperty, + public int $publicIntegerProperty, + protected int $protectedIntegerProperty, + private float $privateFloatProperty, + public float $publicFloatProperty, + protected float $protectedFloatProperty, + private array $privateArrayProperty, + public array $publicArrayProperty, + protected array $protectedArrayProperty, + private $privateAnyTypeProperty, + public $publicAnyTypeProperty, + protected $protectedAnyTypeProperty ) { - $this->privateStringProperty = $privateStringProperty; - $this->publicStringProperty = $publicStringProperty; - $this->protectedStringProperty = $protectedStringProperty; - - $this->privateIntegerProperty = $privateIntegerProperty; - $this->publicIntegerProperty = $publicIntegerProperty; - $this->protectedIntegerProperty = $protectedIntegerProperty; - - $this->privateFloatProperty = $privateFloatProperty; - $this->publicFloatProperty = $publicFloatProperty; - $this->protectedFloatProperty = $protectedFloatProperty; - - $this->privateArrayProperty = $privateArrayProperty; - $this->publicArrayProperty = $publicArrayProperty; - $this->protectedArrayProperty = $protectedArrayProperty; - - $this->privateAnyTypeProperty = $privateAnyTypeProperty; - $this->publicAnyTypeProperty = $publicAnyTypeProperty; - $this->protectedAnyTypeProperty = $protectedAnyTypeProperty; - $this->privateEmptyArrayProperty = []; $this->publicEmptyArrayProperty = []; $this->protectedEmptyArrayProperty = []; @@ -269,63 +228,36 @@ public function producerId(): Domain\Id class EventA implements Event { - private string $property1; - - public function __construct(string $property1) + public function __construct(private string $property1) { - $this->property1 = $property1; } } class EventB extends EventA { - private $property2; - - public function __construct($property1, $property2) + public function __construct($property1, private $property2) { parent::__construct($property1); - $this->property2 = $property2; } } class EventC implements Event { - private Event $event; - - public function __construct(Event $event) + public function __construct(private Event $event) { - $this->event = $event; } } class ParentObject { - private object $objectProperty; - - private string $scalarProperty; - - private array $arrayProperty; - - public function __construct(string $scalarProperty, object $objectProperty, array $arrayProperty) + public function __construct(private string $scalarProperty, private object $objectProperty, private array $arrayProperty) { - $this->objectProperty = $objectProperty; - $this->scalarProperty = $scalarProperty; - $this->arrayProperty = $arrayProperty; } } class ChildObject { - private string $scalarProperty; - - private array $arrayProperty; - - private ?self $child; - - public function __construct(string $scalarProperty, array $arrayProperty, self $childObject = null) + public function __construct(private string $scalarProperty, private array $arrayProperty, private ?self $child = null) { - $this->scalarProperty = $scalarProperty; - $this->arrayProperty = $arrayProperty; - $this->child = $childObject; } } diff --git a/tests/Infrastructure/Domain/Event/Envelope/ComparatorTest.php b/tests/Infrastructure/Domain/Event/Envelope/ComparatorTest.php index eeb15f37..de8afff9 100644 --- a/tests/Infrastructure/Domain/Event/Envelope/ComparatorTest.php +++ b/tests/Infrastructure/Domain/Event/Envelope/ComparatorTest.php @@ -49,8 +49,8 @@ protected function setUp(): void $this->uuid = UUID::random(); $this->event1 = $this->getMockBuilder(Event::class)->getMockForAbstractClass(); - $this->envelope1a = new Event\Envelope($this->uuid, 'name', $this->event1, UUID::random()); - $this->envelope1b = new Event\Envelope($this->uuid, 'name', $this->event1, UUID::random()); + $this->envelope1a = new Event\Envelope($this->uuid, 'name', $this->event1, UUID::random(), UUID::random()); + $this->envelope1b = new Event\Envelope($this->uuid, 'name', $this->event1, UUID::random(), UUID::random()); $this->event2 = $this->getMockBuilder(Event::class)->getMockForAbstractClass(); $this->envelope2 = Event\Envelope::new($this->event2, UUID::random()); } @@ -117,7 +117,15 @@ public function testAccepting($expected, $actual): void public function testEqualEnvelopes(): void { - self::assertNull($this->comparator->assertEquals($this->envelope1a, $this->envelope1b)); +// $this->expectNotToPerformAssertions(); + + try { + $this->comparator->assertEquals($this->envelope1a, $this->envelope1b); + } catch (ComparisonFailure) { + self::fail(); + } + + $this->addToAssertionCount(1); // tests without assertions does not report any coverage, so this is a hack @link https://github.com/sebastianbergmann/phpunit/pull/3348 } public function testNotEqualEnvelopes(): void diff --git a/tests/Infrastructure/Domain/Event/LoggingListenerTest.php b/tests/Infrastructure/Domain/Event/LoggingListenerTest.php index d05347a5..3fb5d3d3 100644 --- a/tests/Infrastructure/Domain/Event/LoggingListenerTest.php +++ b/tests/Infrastructure/Domain/Event/LoggingListenerTest.php @@ -131,11 +131,11 @@ public function testObject(): void $this->listener2 ->expects(self::atLeastOnce()) - ->method('listenerId') + ->method('id') ->willReturn($this->listenerId) ; - self::assertSame($this->listenerId, $listener->listenerId()); + self::assertSame($this->listenerId, $listener->id()); self::assertSame($this->listenerId, $listener->id()); $listener->reset(); diff --git a/tests/Infrastructure/Domain/Event/NullListenerTest.php b/tests/Infrastructure/Domain/Event/NullListenerTest.php index 742b6807..9c76a109 100644 --- a/tests/Infrastructure/Domain/Event/NullListenerTest.php +++ b/tests/Infrastructure/Domain/Event/NullListenerTest.php @@ -41,14 +41,14 @@ public function testObject(): void { $this->listener ->expects(self::atLeastOnce()) - ->method('listenerId') + ->method('id') ->willReturn($this->id) ; $listener = NullListener::from($this->listener); self::assertInstanceOf(NullListener::class, $listener); - self::assertSame($this->id, $listener->listenerId()); + self::assertSame($this->id, $listener->id()); self::assertTrue($listener->on($this->event)); } diff --git a/tests/Infrastructure/Domain/Event/Sourced/Subscription/InMemoryStateTest.php b/tests/Infrastructure/Domain/Event/Sourced/Subscription/InMemoryStateTest.php index 537f0dc0..32da5bf8 100644 --- a/tests/Infrastructure/Domain/Event/Sourced/Subscription/InMemoryStateTest.php +++ b/tests/Infrastructure/Domain/Event/Sourced/Subscription/InMemoryStateTest.php @@ -30,7 +30,7 @@ class InMemoryStateTest extends TestCase protected function setUp(): void { - $this->stub = new class() implements State { + $this->stub = new class () implements State { public function equals(object $object): bool { throw new \BadMethodCallException('Do not call method State::equals() on this stub.'); diff --git a/tests/Infrastructure/Domain/Event/Sourced/SubscriptionTest.php b/tests/Infrastructure/Domain/Event/Sourced/SubscriptionTest.php index 5c2bcab6..94ac2599 100644 --- a/tests/Infrastructure/Domain/Event/Sourced/SubscriptionTest.php +++ b/tests/Infrastructure/Domain/Event/Sourced/SubscriptionTest.php @@ -18,6 +18,7 @@ use Streak\Domain\Event; use Streak\Domain\Event\Listener; use Streak\Domain\EventStore; +use Streak\Domain\Exception\EventMismatched; use Streak\Domain\Id\UUID; use Streak\Infrastructure\Domain\Clock\FixedClock; use Streak\Infrastructure\Domain\Event\InMemoryStream; @@ -83,7 +84,7 @@ protected function setUp(): void $this->listener8 = $this->getMockBuilder(FilteringListener::class)->getMock(); $this->listener9 = $this->getMockBuilder(StatefulListener::class)->getMock(); - $this->id1 = new class('f5e65690-e50d-4312-a175-b004ec1bd42a') extends UUID implements Listener\Id { + $this->id1 = new class ('f5e65690-e50d-4312-a175-b004ec1bd42a') extends UUID implements Listener\Id { }; $this->store = $this->getMockBuilder(EventStore::class)->getMockForAbstractClass(); @@ -111,7 +112,7 @@ public function testListener(): void $this->listener1 ->expects(self::atLeastOnce()) - ->method('listenerId') + ->method('id') ->willReturn($this->id1) ; $this->listener1 @@ -122,9 +123,7 @@ public function testListener(): void $subscription = new Subscription($this->listener1, $this->clock); self::assertSame($subscription->listener(), $this->listener1); - self::assertSame($this->id1, $subscription->subscriptionId()); - self::assertSame($this->id1, $subscription->producerId()); - self::assertNull($subscription->lastReplayed()); + self::assertSame($this->id1, $subscription->id()); self::assertNull($subscription->lastEvent()); self::assertEmpty($subscription->events()); self::assertSame(0, $subscription->version()); @@ -135,9 +134,7 @@ public function testListener(): void $subscription->startFor($this->event1); - self::assertSame($this->id1, $subscription->subscriptionId()); - self::assertSame($this->id1, $subscription->producerId()); - self::assertNull($subscription->lastReplayed()); + self::assertSame($this->id1, $subscription->id()); self::assertSame(0, $subscription->version()); self::assertEquals(new SubscriptionStarted($this->event1, $now), $subscription->lastEvent()); self::assertEquals([new SubscriptionStarted($this->event1, $now)], $subscription->events()); @@ -146,9 +143,7 @@ public function testListener(): void $subscription->commit(); - self::assertSame($this->id1, $subscription->subscriptionId()); - self::assertSame($this->id1, $subscription->producerId()); - self::assertNull($subscription->lastReplayed()); + self::assertSame($this->id1, $subscription->id()); self::assertSame(1, $subscription->version()); self::assertEquals(new SubscriptionStarted($this->event1, $now), $subscription->lastEvent()); self::assertEquals([], $subscription->events()); @@ -295,7 +290,7 @@ public function testListenerWithPicker(): void $this->listener7 ->expects(self::atLeastOnce()) - ->method('listenerId') + ->method('id') ->willReturn($this->id1) ; $this->listener7 @@ -310,18 +305,14 @@ public function testListenerWithPicker(): void $subscription = new Subscription($this->listener7, $this->clock); self::assertSame($subscription->listener(), $this->listener7); - self::assertSame($this->id1, $subscription->subscriptionId()); - self::assertSame($this->id1, $subscription->producerId()); - self::assertNull($subscription->lastReplayed()); + self::assertSame($this->id1, $subscription->id()); self::assertNull($subscription->lastEvent()); self::assertEmpty($subscription->events()); self::assertSame(0, $subscription->version()); $subscription->startFor($this->event3); - self::assertSame($this->id1, $subscription->subscriptionId()); - self::assertSame($this->id1, $subscription->producerId()); - self::assertNull($subscription->lastReplayed()); + self::assertSame($this->id1, $subscription->id()); self::assertSame(0, $subscription->version()); self::assertEquals(new SubscriptionStarted($this->event3, $now), $subscription->lastEvent()); self::assertEquals([new SubscriptionStarted($this->event3, $now)], $subscription->events()); @@ -399,28 +390,25 @@ public function testListenerWithFilterer(): void $this->listener8 ->expects(self::atLeastOnce()) - ->method('listenerId') + ->method('id') ->willReturn($this->id1) ; $subscription = new Subscription($this->listener8, $this->clock); self::assertSame($subscription->listener(), $this->listener8); - self::assertNull($subscription->lastReplayed()); self::assertNull($subscription->lastEvent()); self::assertEmpty($subscription->events()); self::assertSame(0, $subscription->version()); $subscription->startFor($this->event2); - self::assertNull($subscription->lastReplayed()); self::assertSame(0, $subscription->version()); self::assertEquals(new SubscriptionStarted($this->event2, $now), $subscription->lastEvent()); self::assertEquals([new SubscriptionStarted($this->event2, $now)], $subscription->events()); $subscription->commit(); - self::assertNull($subscription->lastReplayed()); self::assertSame(1, $subscription->version()); self::assertEquals(new SubscriptionStarted($this->event2, $now), $subscription->lastEvent()); self::assertEmpty($subscription->events()); @@ -489,7 +477,7 @@ public function testTransactionalListenerWithoutReplaying(): void $this->listener3 ->expects(self::atLeastOnce()) - ->method('listenerId') + ->method('id') ->willReturn($this->id1) ; $this->listener1 @@ -500,27 +488,21 @@ public function testTransactionalListenerWithoutReplaying(): void $subscription = new Subscription($this->listener3, $this->clock); self::assertSame($subscription->listener(), $this->listener3); - self::assertSame($this->id1, $subscription->subscriptionId()); - self::assertSame($this->id1, $subscription->producerId()); - self::assertNull($subscription->lastReplayed()); + self::assertSame($this->id1, $subscription->id()); self::assertNull($subscription->lastEvent()); self::assertEmpty($subscription->events()); self::assertSame(0, $subscription->version()); $subscription->startFor($this->event1); - self::assertSame($this->id1, $subscription->subscriptionId()); - self::assertSame($this->id1, $subscription->producerId()); - self::assertNull($subscription->lastReplayed()); + self::assertSame($this->id1, $subscription->id()); self::assertSame(0, $subscription->version()); self::assertEquals(new SubscriptionStarted($this->event1, $now), $subscription->lastEvent()); self::assertEquals([new SubscriptionStarted($this->event1, $now)], $subscription->events()); $subscription->commit(); - self::assertSame($this->id1, $subscription->subscriptionId()); - self::assertSame($this->id1, $subscription->producerId()); - self::assertNull($subscription->lastReplayed()); + self::assertSame($this->id1, $subscription->id()); self::assertSame(1, $subscription->version()); self::assertEquals(new SubscriptionStarted($this->event1, $now), $subscription->lastEvent()); self::assertEquals([], $subscription->events()); @@ -612,7 +594,7 @@ public function testReplayingListener(): void $this->listener1 ->expects(self::atLeastOnce()) - ->method('listenerId') + ->method('id') ->willReturn($this->id1) ; $this->listener1 @@ -623,9 +605,7 @@ public function testReplayingListener(): void $subscription = new Subscription($this->listener1, $this->clock); self::assertSame($subscription->listener(), $this->listener1); - self::assertSame($this->id1, $subscription->subscriptionId()); - self::assertSame($this->id1, $subscription->producerId()); - self::assertNull($subscription->lastReplayed()); + self::assertSame($this->id1, $subscription->id()); self::assertNull($subscription->lastEvent()); self::assertEmpty($subscription->events()); self::assertSame(0, $subscription->version()); @@ -641,9 +621,7 @@ public function testReplayingListener(): void $subscription->replay($this->stream1); - self::assertSame($this->id1, $subscription->subscriptionId()); - self::assertSame($this->id1, $subscription->producerId()); - self::assertSame($event2, $subscription->lastReplayed()); + self::assertSame($this->id1, $subscription->id()); self::assertSame(3, $subscription->version()); self::assertEquals($event2, $subscription->lastEvent()); self::assertEmpty($subscription->events()); @@ -706,7 +684,7 @@ public function testReplayingStatefulListenerWithExistingState(): void $this->listener9 ->expects(self::atLeastOnce()) - ->method('listenerId') + ->method('id') ->with() ->willReturn($this->id1) ; @@ -714,7 +692,6 @@ public function testReplayingStatefulListenerWithExistingState(): void $subscription = new Subscription($this->listener9, $this->clock); self::assertSame($subscription->listener(), $this->listener9); - self::assertNull($subscription->lastReplayed()); self::assertNull($subscription->lastEvent()); self::assertEmpty($subscription->events()); self::assertSame(0, $subscription->version()); @@ -741,7 +718,6 @@ public function testReplayingStatefulListenerWithExistingState(): void $subscription->replay($this->stream1); - self::assertSame($event3, $subscription->lastReplayed()); self::assertSame(4, $subscription->version()); self::assertEquals($event3, $subscription->lastEvent()); self::assertEmpty($subscription->events()); @@ -813,14 +789,13 @@ public function testReplayingStatefulListenerWithoutExistingState(): void $this->listener9 ->expects(self::atLeastOnce()) - ->method('listenerId') + ->method('id') ->with() ->willReturn($this->id1) ; $subscription = new Subscription($this->listener9, $this->clock); self::assertSame($subscription->listener(), $this->listener9); - self::assertNull($subscription->lastReplayed()); self::assertNull($subscription->lastEvent()); self::assertEmpty($subscription->events()); self::assertSame(0, $subscription->version()); @@ -836,7 +811,6 @@ public function testReplayingStatefulListenerWithoutExistingState(): void $subscription->replay($this->stream1); - self::assertSame($event2, $subscription->lastReplayed()); self::assertSame(3, $subscription->version()); self::assertEquals($event2, $subscription->lastEvent()); self::assertEmpty($subscription->events()); @@ -914,7 +888,7 @@ public function testReplayingListenerWithAnEmptyStream(): void { $this->listener1 ->expects(self::atLeastOnce()) - ->method('listenerId') + ->method('id') ->willReturn($this->id1) ; $this->listener1 @@ -925,9 +899,7 @@ public function testReplayingListenerWithAnEmptyStream(): void $subscription = new Subscription($this->listener1, $this->clock); self::assertSame($subscription->listener(), $this->listener1); - self::assertSame($this->id1, $subscription->subscriptionId()); - self::assertSame($this->id1, $subscription->producerId()); - self::assertNull($subscription->lastReplayed()); + self::assertSame($this->id1, $subscription->id()); self::assertNull($subscription->lastEvent()); self::assertEmpty($subscription->events()); self::assertSame(0, $subscription->version()); @@ -937,9 +909,7 @@ public function testReplayingListenerWithAnEmptyStream(): void $subscription->replay($this->stream1); self::assertSame($subscription->listener(), $this->listener1); - self::assertSame($this->id1, $subscription->subscriptionId()); - self::assertSame($this->id1, $subscription->producerId()); - self::assertNull($subscription->lastReplayed()); + self::assertSame($this->id1, $subscription->id()); self::assertNull($subscription->lastEvent()); self::assertEmpty($subscription->events()); self::assertSame(0, $subscription->version()); @@ -951,7 +921,7 @@ public function testCompletingListener(): void $this->listener3 ->expects(self::atLeastOnce()) - ->method('listenerId') + ->method('id') ->with() ->willReturn($this->id1) ; @@ -960,7 +930,6 @@ public function testCompletingListener(): void self::assertSame($subscription->listener(), $this->listener3); self::assertFalse($subscription->completed()); - self::assertNull($subscription->lastReplayed()); self::assertNull($subscription->lastEvent()); self::assertEmpty($subscription->events()); self::assertSame(0, $subscription->version()); @@ -973,7 +942,6 @@ public function testCompletingListener(): void $subscription->replay($this->stream1); - self::assertSame($event0, $subscription->lastReplayed()); self::assertSame($event0, $subscription->lastEvent()); self::assertEmpty($subscription->events()); self::assertSame(1, $subscription->version()); @@ -1017,7 +985,6 @@ public function testCompletingListener(): void self::assertEquals([$this->event1, $this->event2], $events); self::assertTrue($subscription->completed()); self::assertEquals([new SubscriptionListenedToEvent($this->event1, $now), new SubscriptionListenedToEvent($this->event2, $now), new SubscriptionCompleted($now)], $subscription->events()); - self::assertSame($event0, $subscription->lastReplayed()); self::assertEquals(new SubscriptionCompleted($now), $subscription->lastEvent()); self::assertSame(1, $subscription->version()); self::assertFalse($subscription->paused()); @@ -1026,7 +993,6 @@ public function testCompletingListener(): void self::assertTrue($subscription->completed()); self::assertEmpty($subscription->events()); - self::assertSame($event0, $subscription->lastReplayed()); self::assertEquals(new SubscriptionCompleted($now), $subscription->lastEvent()); self::assertSame(4, $subscription->version()); self::assertFalse($subscription->paused()); @@ -1035,7 +1001,6 @@ public function testCompletingListener(): void self::assertTrue($subscription->completed()); self::assertEmpty($subscription->events()); - self::assertSame($event0, $subscription->lastReplayed()); self::assertEquals(new SubscriptionCompleted($now), $subscription->lastEvent()); self::assertSame(4, $subscription->version()); self::assertFalse($subscription->paused()); @@ -1044,7 +1009,6 @@ public function testCompletingListener(): void self::assertTrue($subscription->completed()); self::assertEmpty($subscription->events()); - self::assertSame($event0, $subscription->lastReplayed()); self::assertEquals(new SubscriptionCompleted($now), $subscription->lastEvent()); self::assertSame(4, $subscription->version()); self::assertFalse($subscription->paused()); @@ -1053,7 +1017,6 @@ public function testCompletingListener(): void self::assertTrue($subscription->completed()); self::assertEmpty($subscription->events()); - self::assertSame($event0, $subscription->lastReplayed()); self::assertEquals(new SubscriptionCompleted($now), $subscription->lastEvent()); self::assertSame(4, $subscription->version()); self::assertFalse($subscription->paused()); @@ -1062,7 +1025,6 @@ public function testCompletingListener(): void self::assertTrue($subscription->completed()); self::assertEmpty($subscription->events()); - self::assertSame($event0, $subscription->lastReplayed()); self::assertEquals(new SubscriptionCompleted($now), $subscription->lastEvent()); self::assertSame(4, $subscription->version()); self::assertFalse($subscription->paused()); @@ -1078,16 +1040,14 @@ public function testStartingAlreadyStartedSubscription(): void { $this->listener1 ->expects(self::atLeastOnce()) - ->method('listenerId') + ->method('id') ->willReturn($this->id1) ; $subscription = new Subscription($this->listener1, $this->clock); self::assertSame($subscription->listener(), $this->listener1); - self::assertSame($this->id1, $subscription->subscriptionId()); - self::assertSame($this->id1, $subscription->producerId()); - self::assertNull($subscription->lastReplayed()); + self::assertSame($this->id1, $subscription->id()); self::assertNull($subscription->lastEvent()); self::assertEmpty($subscription->events()); @@ -1104,7 +1064,7 @@ public function testSubscribingAlreadyCompletedListener(): void $this->listener3 ->expects(self::atLeastOnce()) - ->method('listenerId') + ->method('id') ->with() ->willReturn($this->id1) ; @@ -1126,7 +1086,6 @@ public function testSubscribingAlreadyCompletedListener(): void $subscription->replay($this->stream1); self::assertTrue($subscription->completed()); - self::assertSame($event2, $subscription->lastReplayed()); self::assertSame($event2, $subscription->lastEvent()); self::assertEmpty($subscription->events()); self::assertSame(3, $subscription->version()); @@ -1149,7 +1108,7 @@ public function testSubscribingRestartedAndCompletedListener(): void $this->listener3 ->expects(self::atLeastOnce()) - ->method('listenerId') + ->method('id') ->with() ->willReturn($this->id1) ; @@ -1177,7 +1136,6 @@ public function testSubscribingRestartedAndCompletedListener(): void $subscription->replay($this->stream1); self::assertTrue($subscription->completed()); - self::assertSame($event5, $subscription->lastReplayed()); self::assertSame($event5, $subscription->lastEvent()); self::assertEmpty($subscription->events()); self::assertSame(6, $subscription->version()); @@ -1198,16 +1156,14 @@ public function testNotStartedListener(): void { $this->listener1 ->expects(self::atLeastOnce()) - ->method('listenerId') + ->method('id') ->willReturn($this->id1) ; $subscription = new Subscription($this->listener1, $this->clock); self::assertSame($subscription->listener(), $this->listener1); - self::assertSame($this->id1, $subscription->subscriptionId()); - self::assertSame($this->id1, $subscription->producerId()); - self::assertNull($subscription->lastReplayed()); + self::assertSame($this->id1, $subscription->id()); self::assertNull($subscription->lastEvent()); self::assertEmpty($subscription->events()); @@ -1232,7 +1188,7 @@ public function testRestartingSubscriptionForResettableButNonReplayableListener( { $this->listener4 ->expects(self::atLeastOnce()) - ->method('listenerId') + ->method('id') ->with() ->willReturn($this->id1) ; @@ -1240,7 +1196,6 @@ public function testRestartingSubscriptionForResettableButNonReplayableListener( $subscription = new Subscription($this->listener4, $this->clock); self::assertSame($subscription->listener(), $this->listener4); - self::assertNull($subscription->lastReplayed()); self::assertNull($subscription->lastEvent()); self::assertEmpty($subscription->events()); self::assertSame(0, $subscription->version()); @@ -1259,21 +1214,18 @@ public function testRestartingSubscriptionForResettableButNonReplayableListener( $subscription->replay($this->stream1); - self::assertSame($event3, $subscription->lastReplayed()); self::assertSame($event3, $subscription->lastEvent()); self::assertSame([], $subscription->events()); self::assertSame(4, $subscription->version()); $subscription->restart(); - self::assertSame($event3, $subscription->lastReplayed()); self::assertEquals(new SubscriptionRestarted($this->event1, $now), $subscription->lastEvent()); self::assertEquals([new SubscriptionRestarted($this->event1, $now)], $subscription->events()); self::assertSame(4, $subscription->version()); $subscription->commit(); - self::assertSame($event3, $subscription->lastReplayed()); self::assertEquals(new SubscriptionRestarted($this->event1, $now), $subscription->lastEvent()); self::assertSame([], $subscription->events()); self::assertSame(5, $subscription->version()); @@ -1281,7 +1233,6 @@ public function testRestartingSubscriptionForResettableButNonReplayableListener( $subscription->restart(); // nothing changed as consecutive restarts are ignored - self::assertSame($event3, $subscription->lastReplayed()); self::assertEquals(new SubscriptionRestarted($this->event1, $now), $subscription->lastEvent()); self::assertSame([], $subscription->events()); self::assertSame(5, $subscription->version()); @@ -1319,14 +1270,12 @@ public function testRestartingSubscriptionForResettableButNonReplayableListener( $events = iterator_to_array($events); self::assertSame([$this->event1, $this->event3, $this->event4, $this->event5], $events); - self::assertSame($event3, $subscription->lastReplayed()); self::assertEquals(new SubscriptionListenedToEvent($this->event5, $now), $subscription->lastEvent()); self::assertEquals([new SubscriptionListenedToEvent($this->event1, $now), new SubscriptionListenedToEvent($this->event3, $now), new SubscriptionIgnoredEvent($this->event4, $now), new SubscriptionListenedToEvent($this->event5, $now)], $subscription->events()); self::assertSame(5, $subscription->version()); $subscription->commit(); - self::assertSame($event3, $subscription->lastReplayed()); self::assertEquals(new SubscriptionListenedToEvent($this->event5, $now), $subscription->lastEvent()); self::assertSame([], $subscription->events()); self::assertSame(9, $subscription->version()); @@ -1336,16 +1285,14 @@ public function testRestartingNotStartedSubscription(): void { $this->listener1 ->expects(self::atLeastOnce()) - ->method('listenerId') + ->method('id') ->willReturn($this->id1) ; $subscription = new Subscription($this->listener1, $this->clock); self::assertSame($subscription->listener(), $this->listener1); - self::assertSame($this->id1, $subscription->subscriptionId()); - self::assertSame($this->id1, $subscription->producerId()); - self::assertNull($subscription->lastReplayed()); + self::assertSame($this->id1, $subscription->id()); self::assertNull($subscription->lastEvent()); self::assertEmpty($subscription->events()); @@ -1358,7 +1305,7 @@ public function testRestartingCompletedSubscription(): void { $this->listener6 ->expects(self::atLeastOnce()) - ->method('listenerId') + ->method('id') ->with() ->willReturn($this->id1) ; @@ -1366,7 +1313,6 @@ public function testRestartingCompletedSubscription(): void $subscription = new Subscription($this->listener6, $this->clock); self::assertSame($subscription->listener(), $this->listener6); - self::assertNull($subscription->lastReplayed()); self::assertNull($subscription->lastEvent()); self::assertEmpty($subscription->events()); self::assertSame(0, $subscription->version()); @@ -1403,7 +1349,6 @@ public function testRestartingCompletedSubscription(): void $subscription->replay($this->stream1); - self::assertSame($event3, $subscription->lastReplayed()); self::assertSame($event3, $subscription->lastEvent()); self::assertSame([], $subscription->events()); self::assertSame(4, $subscription->version()); @@ -1411,7 +1356,6 @@ public function testRestartingCompletedSubscription(): void $subscription->restart(); - self::assertSame($event3, $subscription->lastReplayed()); self::assertEquals(new SubscriptionRestarted($this->event2, $now), $subscription->lastEvent()); self::assertEquals([new SubscriptionRestarted($this->event2, $now)], $subscription->events()); self::assertSame(4, $subscription->version()); @@ -1419,7 +1363,6 @@ public function testRestartingCompletedSubscription(): void $subscription->commit(); - self::assertSame($event3, $subscription->lastReplayed()); self::assertEquals(new SubscriptionRestarted($this->event2, $now), $subscription->lastEvent()); self::assertSame([], $subscription->events()); self::assertSame(5, $subscription->version()); @@ -1453,7 +1396,6 @@ public function testRestartingCompletedSubscription(): void $events = iterator_to_array($events); self::assertSame([$this->event2, $this->event3, $this->event4, $this->event5], $events); - self::assertSame($event3, $subscription->lastReplayed()); self::assertEquals(new SubscriptionListenedToEvent($this->event5, $now), $subscription->lastEvent()); self::assertEquals([new SubscriptionListenedToEvent($this->event2, $now), new SubscriptionListenedToEvent($this->event3, $now), new SubscriptionListenedToEvent($this->event4, $now), new SubscriptionListenedToEvent($this->event5, $now)], $subscription->events()); self::assertSame(5, $subscription->version()); @@ -1461,7 +1403,6 @@ public function testRestartingCompletedSubscription(): void $subscription->commit(); - self::assertSame($event3, $subscription->lastReplayed()); self::assertEquals(new SubscriptionListenedToEvent($this->event5, $now), $subscription->lastEvent()); self::assertSame([], $subscription->events()); self::assertSame(9, $subscription->version()); @@ -1472,7 +1413,7 @@ public function testRestartingNonResettableListener(): void { $this->listener1 ->expects(self::atLeastOnce()) - ->method('listenerId') + ->method('id') ->with() ->willReturn($this->id1) ; @@ -1481,7 +1422,6 @@ public function testRestartingNonResettableListener(): void self::assertSame($subscription->listener(), $this->listener1); self::assertFalse($subscription->completed()); - self::assertNull($subscription->lastReplayed()); self::assertNull($subscription->lastEvent()); self::assertEmpty($subscription->events()); self::assertSame(0, $subscription->version()); @@ -1499,7 +1439,6 @@ public function testRestartingNonResettableListener(): void $subscription->replay($this->stream1); - self::assertSame($event2, $subscription->lastReplayed()); self::assertSame($event2, $subscription->lastEvent()); self::assertEmpty($subscription->events()); self::assertSame(3, $subscription->version()); @@ -1528,13 +1467,13 @@ public function testEquals(): void $this->listener1 ->expects(self::atLeastOnce()) - ->method('listenerId') + ->method('id') ->willReturn($id1) ; $this->listener3 ->expects(self::atLeastOnce()) - ->method('listenerId') + ->method('id') ->willReturn($id2) ; @@ -1563,33 +1502,28 @@ public function testStartingSubscriptionWithResettableListenerWithFirstEventIgno $this->listener4 ->expects(self::atLeastOnce()) - ->method('listenerId') + ->method('id') ->willReturn($this->id1) ; $subscription = new Subscription($this->listener4, $this->clock); self::assertSame($subscription->listener(), $this->listener4); - self::assertSame($this->id1, $subscription->subscriptionId()); - self::assertSame($this->id1, $subscription->producerId()); - self::assertNull($subscription->lastReplayed()); + self::assertSame($this->id1, $subscription->id()); self::assertNull($subscription->lastEvent()); self::assertEmpty($subscription->events()); self::assertSame(0, $subscription->version()); $subscription->startFor($this->event1); - self::assertSame($this->id1, $subscription->subscriptionId()); - self::assertSame($this->id1, $subscription->producerId()); - self::assertNull($subscription->lastReplayed()); + self::assertSame($this->id1, $subscription->id()); + self::assertSame(0, $subscription->version()); self::assertEquals(new SubscriptionStarted($this->event1, $now), $subscription->lastEvent()); self::assertEquals([new SubscriptionStarted($this->event1, $now)], $subscription->events()); $subscription->commit(); - self::assertSame($this->id1, $subscription->subscriptionId()); - self::assertSame($this->id1, $subscription->producerId()); - self::assertNull($subscription->lastReplayed()); + self::assertSame($this->id1, $subscription->id()); self::assertSame(1, $subscription->version()); self::assertEquals(new SubscriptionStarted($this->event1, $now), $subscription->lastEvent()); self::assertEquals([], $subscription->events()); @@ -1633,33 +1567,27 @@ public function testStartingSubscriptionWithResettableListenerWithFirstEventNotI $this->listener4 ->expects(self::atLeastOnce()) - ->method('listenerId') + ->method('id') ->willReturn($this->id1) ; $subscription = new Subscription($this->listener4, $this->clock); self::assertSame($subscription->listener(), $this->listener4); - self::assertSame($this->id1, $subscription->subscriptionId()); - self::assertSame($this->id1, $subscription->producerId()); - self::assertNull($subscription->lastReplayed()); + self::assertSame($this->id1, $subscription->id()); self::assertNull($subscription->lastEvent()); self::assertEmpty($subscription->events()); self::assertSame(0, $subscription->version()); $subscription->startFor($this->event1); - self::assertSame($this->id1, $subscription->subscriptionId()); - self::assertSame($this->id1, $subscription->producerId()); - self::assertNull($subscription->lastReplayed()); + self::assertSame($this->id1, $subscription->id()); self::assertSame(0, $subscription->version()); self::assertEquals(new SubscriptionStarted($this->event1, $now), $subscription->lastEvent()); self::assertEquals([new SubscriptionStarted($this->event1, $now)], $subscription->events()); $subscription->commit(); - self::assertSame($this->id1, $subscription->subscriptionId()); - self::assertSame($this->id1, $subscription->producerId()); - self::assertNull($subscription->lastReplayed()); + self::assertSame($this->id1, $subscription->id()); self::assertSame(1, $subscription->version()); self::assertEquals(new SubscriptionStarted($this->event1, $now), $subscription->lastEvent()); self::assertEquals([], $subscription->events()); @@ -1703,33 +1631,27 @@ public function testRestartingFreshlyStartedSubscription(): void $this->listener4 ->expects(self::atLeastOnce()) - ->method('listenerId') + ->method('id') ->willReturn($this->id1) ; $subscription = new Subscription($this->listener4, $this->clock); self::assertSame($subscription->listener(), $this->listener4); - self::assertSame($this->id1, $subscription->subscriptionId()); - self::assertSame($this->id1, $subscription->producerId()); - self::assertNull($subscription->lastReplayed()); + self::assertSame($this->id1, $subscription->id()); self::assertNull($subscription->lastEvent()); self::assertEmpty($subscription->events()); self::assertSame(0, $subscription->version()); $subscription->startFor($this->event1); - self::assertSame($this->id1, $subscription->subscriptionId()); - self::assertSame($this->id1, $subscription->producerId()); - self::assertNull($subscription->lastReplayed()); + self::assertSame($this->id1, $subscription->id()); self::assertSame(0, $subscription->version()); self::assertEquals(new SubscriptionStarted($this->event1, $now), $subscription->lastEvent()); self::assertEquals([new SubscriptionStarted($this->event1, $now)], $subscription->events()); $subscription->commit(); - self::assertSame($this->id1, $subscription->subscriptionId()); - self::assertSame($this->id1, $subscription->producerId()); - self::assertNull($subscription->lastReplayed()); + self::assertSame($this->id1, $subscription->id()); self::assertSame(1, $subscription->version()); self::assertEquals(new SubscriptionStarted($this->event1, $now), $subscription->lastEvent()); self::assertEquals([], $subscription->events()); @@ -1737,9 +1659,7 @@ public function testRestartingFreshlyStartedSubscription(): void $subscription->restart(); // nothing changed as consecutive restarts are ignored - self::assertSame($this->id1, $subscription->subscriptionId()); - self::assertSame($this->id1, $subscription->producerId()); - self::assertNull($subscription->lastReplayed()); + self::assertSame($this->id1, $subscription->id()); self::assertSame(1, $subscription->version()); self::assertEquals(new SubscriptionStarted($this->event1, $now), $subscription->lastEvent()); self::assertEquals([], $subscription->events()); @@ -1773,7 +1693,7 @@ public function testNonPositiveLimitGivenWhileSubscribingToTheEventStoreAfterSta { $this->listener1 ->expects(self::atLeastOnce()) - ->method('listenerId') + ->method('id') ->with() ->willReturn($this->id1) ; @@ -1808,7 +1728,7 @@ public function testContinuousListeningWithNumberOfEventsBeingExactlyImposedLimi $this->listener1 ->expects(self::atLeastOnce()) - ->method('listenerId') + ->method('id') ->willReturn($this->id1) ; $this->listener1 @@ -1819,27 +1739,21 @@ public function testContinuousListeningWithNumberOfEventsBeingExactlyImposedLimi $subscription = new Subscription($this->listener1, $this->clock); self::assertSame($subscription->listener(), $this->listener1); - self::assertSame($this->id1, $subscription->subscriptionId()); - self::assertSame($this->id1, $subscription->producerId()); - self::assertNull($subscription->lastReplayed()); + self::assertSame($this->id1, $subscription->id()); self::assertNull($subscription->lastEvent()); self::assertEmpty($subscription->events()); self::assertSame(0, $subscription->version()); $subscription->startFor($this->event1); - self::assertSame($this->id1, $subscription->subscriptionId()); - self::assertSame($this->id1, $subscription->producerId()); - self::assertNull($subscription->lastReplayed()); + self::assertSame($this->id1, $subscription->id()); self::assertSame(0, $subscription->version()); self::assertEquals(new SubscriptionStarted($this->event1, $now), $subscription->lastEvent()); self::assertEquals([new SubscriptionStarted($this->event1, $now)], $subscription->events()); $subscription->commit(); - self::assertSame($this->id1, $subscription->subscriptionId()); - self::assertSame($this->id1, $subscription->producerId()); - self::assertNull($subscription->lastReplayed()); + self::assertSame($this->id1, $subscription->id()); self::assertSame(1, $subscription->version()); self::assertEquals(new SubscriptionStarted($this->event1, $now), $subscription->lastEvent()); self::assertEquals([], $subscription->events()); @@ -1900,7 +1814,7 @@ public function testContinuousListeningWithNumberOfEventsBeingMoreThanImposedLim $this->listener1 ->expects(self::atLeastOnce()) - ->method('listenerId') + ->method('id') ->willReturn($this->id1) ; $this->listener1 @@ -1911,27 +1825,21 @@ public function testContinuousListeningWithNumberOfEventsBeingMoreThanImposedLim $subscription = new Subscription($this->listener1, $this->clock); self::assertSame($subscription->listener(), $this->listener1); - self::assertSame($this->id1, $subscription->subscriptionId()); - self::assertSame($this->id1, $subscription->producerId()); - self::assertNull($subscription->lastReplayed()); + self::assertSame($this->id1, $subscription->id()); self::assertNull($subscription->lastEvent()); self::assertEmpty($subscription->events()); self::assertSame(0, $subscription->version()); $subscription->startFor($this->event1); - self::assertSame($this->id1, $subscription->subscriptionId()); - self::assertSame($this->id1, $subscription->producerId()); - self::assertNull($subscription->lastReplayed()); + self::assertSame($this->id1, $subscription->id()); self::assertSame(0, $subscription->version()); self::assertEquals(new SubscriptionStarted($this->event1, $now), $subscription->lastEvent()); self::assertEquals([new SubscriptionStarted($this->event1, $now)], $subscription->events()); $subscription->commit(); - self::assertSame($this->id1, $subscription->subscriptionId()); - self::assertSame($this->id1, $subscription->producerId()); - self::assertNull($subscription->lastReplayed()); + self::assertSame($this->id1, $subscription->id()); self::assertSame(1, $subscription->version()); self::assertEquals(new SubscriptionStarted($this->event1, $now), $subscription->lastEvent()); self::assertEquals([], $subscription->events()); @@ -1988,7 +1896,7 @@ public function testContinuousListeningWithNumberOfEventsBeingMoreThanImposedLim $this->listener1 ->expects(self::atLeastOnce()) - ->method('listenerId') + ->method('id') ->willReturn($this->id1) ; $this->listener1 @@ -1999,27 +1907,21 @@ public function testContinuousListeningWithNumberOfEventsBeingMoreThanImposedLim $subscription = new Subscription($this->listener1, $this->clock); self::assertSame($subscription->listener(), $this->listener1); - self::assertSame($this->id1, $subscription->subscriptionId()); - self::assertSame($this->id1, $subscription->producerId()); - self::assertNull($subscription->lastReplayed()); + self::assertSame($this->id1, $subscription->id()); self::assertNull($subscription->lastEvent()); self::assertEmpty($subscription->events()); self::assertSame(0, $subscription->version()); $subscription->startFor($this->event1); - self::assertSame($this->id1, $subscription->subscriptionId()); - self::assertSame($this->id1, $subscription->producerId()); - self::assertNull($subscription->lastReplayed()); + self::assertSame($this->id1, $subscription->id()); self::assertSame(0, $subscription->version()); self::assertEquals(new SubscriptionStarted($this->event1, $now), $subscription->lastEvent()); self::assertEquals([new SubscriptionStarted($this->event1, $now)], $subscription->events()); $subscription->commit(); - self::assertSame($this->id1, $subscription->subscriptionId()); - self::assertSame($this->id1, $subscription->producerId()); - self::assertNull($subscription->lastReplayed()); + self::assertSame($this->id1, $subscription->id()); self::assertSame(1, $subscription->version()); self::assertEquals(new SubscriptionStarted($this->event1, $now), $subscription->lastEvent()); self::assertEquals([], $subscription->events()); @@ -2076,7 +1978,7 @@ public function testContinuousListeningWithNumberOfEventsBeingLessThanImposedLim $this->listener1 ->expects(self::atLeastOnce()) - ->method('listenerId') + ->method('id') ->willReturn($this->id1) ; $this->listener1 @@ -2087,27 +1989,21 @@ public function testContinuousListeningWithNumberOfEventsBeingLessThanImposedLim $subscription = new Subscription($this->listener1, $this->clock); self::assertSame($subscription->listener(), $this->listener1); - self::assertSame($this->id1, $subscription->subscriptionId()); - self::assertSame($this->id1, $subscription->producerId()); - self::assertNull($subscription->lastReplayed()); + self::assertSame($this->id1, $subscription->id()); self::assertNull($subscription->lastEvent()); self::assertEmpty($subscription->events()); self::assertSame(0, $subscription->version()); $subscription->startFor($this->event1); - self::assertSame($this->id1, $subscription->subscriptionId()); - self::assertSame($this->id1, $subscription->producerId()); - self::assertNull($subscription->lastReplayed()); + self::assertSame($this->id1, $subscription->id()); self::assertSame(0, $subscription->version()); self::assertEquals(new SubscriptionStarted($this->event1, $now), $subscription->lastEvent()); self::assertEquals([new SubscriptionStarted($this->event1, $now)], $subscription->events()); $subscription->commit(); - self::assertSame($this->id1, $subscription->subscriptionId()); - self::assertSame($this->id1, $subscription->producerId()); - self::assertNull($subscription->lastReplayed()); + self::assertSame($this->id1, $subscription->id()); self::assertSame(1, $subscription->version()); self::assertEquals(new SubscriptionStarted($this->event1, $now), $subscription->lastEvent()); self::assertEquals([], $subscription->events()); @@ -2168,34 +2064,28 @@ public function testCompletingListenerWhileContinuousListening(): void $this->listener3 ->expects(self::atLeastOnce()) - ->method('listenerId') + ->method('id') ->willReturn($this->id1) ; $subscription = new Subscription($this->listener3, $this->clock); self::assertSame($subscription->listener(), $this->listener3); - self::assertSame($this->id1, $subscription->subscriptionId()); - self::assertSame($this->id1, $subscription->producerId()); - self::assertNull($subscription->lastReplayed()); + self::assertSame($this->id1, $subscription->id()); self::assertNull($subscription->lastEvent()); self::assertEmpty($subscription->events()); self::assertSame(0, $subscription->version()); $subscription->startFor($this->event1); - self::assertSame($this->id1, $subscription->subscriptionId()); - self::assertSame($this->id1, $subscription->producerId()); - self::assertNull($subscription->lastReplayed()); + self::assertSame($this->id1, $subscription->id()); self::assertSame(0, $subscription->version()); self::assertEquals(new SubscriptionStarted($this->event1, $now), $subscription->lastEvent()); self::assertEquals([new SubscriptionStarted($this->event1, $now)], $subscription->events()); $subscription->commit(); - self::assertSame($this->id1, $subscription->subscriptionId()); - self::assertSame($this->id1, $subscription->producerId()); - self::assertNull($subscription->lastReplayed()); + self::assertSame($this->id1, $subscription->id()); self::assertSame(1, $subscription->version()); self::assertEquals(new SubscriptionStarted($this->event1, $now), $subscription->lastEvent()); self::assertEquals([], $subscription->events()); @@ -2256,6 +2146,51 @@ public function testCompletingListenerWhileContinuousListening(): void self::assertEquals([], $subscription->events()); self::assertSame(7, $subscription->version()); } + + public function testReplayingMismatchedEvent(): void + { + $now = new \DateTime('2018-09-28 19:12:32.763188 +00:00'); + + $this->listener1 + ->expects(self::atLeastOnce()) + ->method('id') + ->willReturn($this->id1) + ; + $this->listener1 + ->expects(self::never()) + ->method('replay') + ; + + $subscription = new Subscription($this->listener1, $this->clock); + + self::assertSame($subscription->listener(), $this->listener1); + self::assertSame($this->id1, $subscription->id()); + self::assertNull($subscription->lastEvent()); + self::assertEmpty($subscription->events()); + self::assertSame(0, $subscription->version()); + + $event0 = new SubscriptionStarted($this->event1, $now); + $event0 = Event\Envelope::new($event0, $this->id1, 1); + $event1 = new SubscriptionListenedToEvent($this->event1, $now); + $event1 = Event\Envelope::new($event1, $this->id1, 2); + $event2 = new SubscriptionListenedToEvent($this->event2, $now); + $event2 = Event\Envelope::new($event2, UUID::random(), 3); + + $this->stream1 = new InMemoryStream($event0, $event1, $event2); + + try { + $subscription->replay($this->stream1); + self::fail(); + } catch (EventMismatched $exception) { + self::assertSame($event2, $exception->event()); + self::assertSame($subscription, $exception->object()); + + self::assertSame($this->id1, $subscription->id()); + self::assertSame(1, $subscription->version()); + self::assertEquals($event0, $subscription->lastEvent()); + self::assertEmpty($subscription->events()); + } + } } namespace Streak\Infrastructure\Domain\Event\Sourced\SubscriptionTest; @@ -2290,3 +2225,7 @@ abstract class StatefulListener implements Listener, Listener\Stateful abstract class IterableStream implements Event\Stream, \IteratorAggregate { } + +class UnsupportedEvent implements Event +{ +} diff --git a/tests/Infrastructure/Domain/Event/Subscription/CommittingSubscriptionTest.php b/tests/Infrastructure/Domain/Event/Subscription/CommittingSubscriptionTest.php index 8fc294af..6e7286f3 100644 --- a/tests/Infrastructure/Domain/Event/Subscription/CommittingSubscriptionTest.php +++ b/tests/Infrastructure/Domain/Event/Subscription/CommittingSubscriptionTest.php @@ -43,7 +43,7 @@ protected function setUp(): void { $this->listener = $this->getMockBuilder(Listener::class)->addMethods(['replay', 'reset', 'completed'])->getMockForAbstractClass(); - $this->id1 = new class('f5e65690-e50d-4312-a175-b004ec1bd42a') extends UUID implements Listener\Id { + $this->id1 = new class ('f5e65690-e50d-4312-a175-b004ec1bd42a') extends UUID implements Listener\Id { }; $this->store = $this->getMockBuilder(EventStore::class)->getMockForAbstractClass(); @@ -68,7 +68,7 @@ public function testListener(): void ; $this->subscription ->expects(self::atLeastOnce()) - ->method('subscriptionId') + ->method('id') ->willReturn($this->id1) ; $this->subscription @@ -98,7 +98,7 @@ public function testListener(): void ; self::assertSame($this->listener, $subscription->listener()); - self::assertSame($this->id1, $subscription->subscriptionId()); + self::assertSame($this->id1, $subscription->id()); self::assertSame(\PHP_INT_MAX, $subscription->version()); self::assertTrue($subscription->starting()); self::assertFalse($subscription->starting()); diff --git a/tests/Infrastructure/Domain/Event/Subscription/DAO/DAOTestCase.php b/tests/Infrastructure/Domain/Event/Subscription/DAO/DAOTestCase.php index a5eb61a7..e1b00715 100644 --- a/tests/Infrastructure/Domain/Event/Subscription/DAO/DAOTestCase.php +++ b/tests/Infrastructure/Domain/Event/Subscription/DAO/DAOTestCase.php @@ -46,8 +46,8 @@ protected function setUp(): void { $this->subscriptions = $this->getMockBuilder(Event\Subscription\Factory::class)->getMockForAbstractClass(); $this->listeners = $this->getMockBuilder(Event\Listener\Factory::class)->getMockForAbstractClass(); - $this->listener1 = $this->getMockBuilder(CompletableListener::class)->setMockClassName('listener1')->getMock(); - $this->listener2 = $this->getMockBuilder(CompletableListener::class)->setMockClassName('listener2')->getMock(); + $this->listener1 = $this->getMockBuilder(CompletableListener::class)->setMockClassName('listener1_sydteu')->getMockForAbstractClass(); + $this->listener2 = $this->getMockBuilder(CompletableListener::class)->setMockClassName('listener2_dhafg6')->getMockForAbstractClass(); $this->event = Event\Envelope::new(new EventStub(), UUID::random()); $this->clock = new FixedClock(new \DateTime('2018-09-28 19:12:32.763188 +00:00')); $this->dao = $this->newDAO(new Subscription\Factory($this->clock), $this->listeners); @@ -70,22 +70,23 @@ public function testDAO(): void $this->listener1 ->expects(self::atLeastOnce()) - ->method('listenerId') + ->method('id') ->willReturn($listenerId1) ; $this->listener2 ->expects(self::atLeastOnce()) - ->method('listenerId') + ->method('id') ->willReturn($listenerId2) ; $this->listener1 + ->expects(self::atLeastOnce()) ->method('completed') ->willReturnOnConsecutiveCalls(false, true) ; $this->listener2 + ->expects(self::never()) ->method('completed') - ->willReturnOnConsecutiveCalls(false, false) ; $all = $this->dao->all(); diff --git a/tests/Infrastructure/Domain/Event/Subscription/DAO/DbalPostgresDAOTest.php b/tests/Infrastructure/Domain/Event/Subscription/DAO/DbalPostgresDAOTest.php index 44385979..be2164d5 100644 --- a/tests/Infrastructure/Domain/Event/Subscription/DAO/DbalPostgresDAOTest.php +++ b/tests/Infrastructure/Domain/Event/Subscription/DAO/DbalPostgresDAOTest.php @@ -59,7 +59,7 @@ public function testDAO(): void $listener3 = $this->getMockBuilder(DAO\DbalPostgresDAOTest\CompletableListener::class)->setMockClassName('listener3')->getMock(); $listener3 ->expects(self::atLeastOnce()) - ->method('listenerId') + ->method('id') ->willReturn($listenerId3) ; $subscription3 = new Subscription($listener3, $this->clock); diff --git a/tests/Infrastructure/Domain/Event/Subscription/DAO/IdentityMappingDaoTest.php b/tests/Infrastructure/Domain/Event/Subscription/DAO/IdentityMappingDaoTest.php index 714714b0..b7adcdef 100644 --- a/tests/Infrastructure/Domain/Event/Subscription/DAO/IdentityMappingDaoTest.php +++ b/tests/Infrastructure/Domain/Event/Subscription/DAO/IdentityMappingDaoTest.php @@ -15,10 +15,7 @@ use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; -use Streak\Domain\Event; -use Streak\Domain\Event\Envelope; use Streak\Domain\Event\Listener\Id; -use Streak\Domain\Id\UUID; use Streak\Infrastructure\Domain\Event\Subscription\DAO; /** @@ -159,7 +156,7 @@ public function testItReturnsOne(): void $subscription = $this->createSubscriptionStub('eea81580-4e00-4680-8f87-e96054d3c41b', 'SubscriptionId', 100); $this->dao->expects(self::once())->method('one')->willReturn($subscription); $dao = new IdentityMappingDao($this->dao); - self::assertSame($subscription, $dao->one($subscription->subscriptionId())); + self::assertSame($subscription, $dao->one($subscription->id())); } public function testItExists(): void @@ -175,19 +172,12 @@ public function testItExists(): void private function createSubscriptionStub(string $subscriptionId, string $subscriptionIdClassName, int $version): Subscription { $result = $this->getMockBuilder(Subscription::class)->disableOriginalConstructor()->getMock(); - $result->method('subscriptionId')->willReturn($this->createSubscriptionIdStub($subscriptionIdClassName, $subscriptionId)); + $result->method('id')->willReturn($this->createSubscriptionIdStub($subscriptionIdClassName, $subscriptionId)); $result->method('version')->willReturn($version); return $result; } - private function createEnvelopeStub(string $id): Envelope - { - $event = $this->getMockBuilder(Event::class)->getMock(); - - return new Envelope(new UUID($id), 'test', $event, new UUID($id)); - } - private function createSubscriptionIdStub(string $className, string $id): Id { $result = $this->getMockBuilder(Id::class)->setMockClassName($className)->getMock(); diff --git a/tests/Infrastructure/Domain/Event/Subscription/DAO/SubscriptionTest.php b/tests/Infrastructure/Domain/Event/Subscription/DAO/SubscriptionTest.php index bc81e8ac..d67f1a7e 100644 --- a/tests/Infrastructure/Domain/Event/Subscription/DAO/SubscriptionTest.php +++ b/tests/Infrastructure/Domain/Event/Subscription/DAO/SubscriptionTest.php @@ -68,7 +68,7 @@ protected function setUp(): void $this->listener8 = $this->getMockBuilder(FilteringListener::class)->getMock(); $this->listener9 = $this->getMockBuilder(StatefulListener::class)->getMock(); - $this->id1 = new class('f5e65690-e50d-4312-a175-b004ec1bd42a') extends UUID implements Listener\Id { + $this->id1 = new class ('f5e65690-e50d-4312-a175-b004ec1bd42a') extends UUID implements Listener\Id { }; $this->store = $this->getMockBuilder(EventStore::class)->getMockForAbstractClass(); @@ -90,7 +90,7 @@ public function testListener(): void { $this->listener1 ->expects(self::atLeastOnce()) - ->method('listenerId') + ->method('id') ->willReturn($this->id1) ; $this->listener1 @@ -101,7 +101,7 @@ public function testListener(): void $subscription = new Subscription($this->listener1, $this->clock); self::assertSame($subscription->listener(), $this->listener1); - self::assertSame($this->id1, $subscription->subscriptionId()); + self::assertSame($this->id1, $subscription->id()); self::assertSame(0, $subscription->version()); self::assertFalse($subscription->starting()); self::assertFalse($subscription->paused()); @@ -111,7 +111,7 @@ public function testListener(): void $subscription->startFor($this->event1); - self::assertSame($this->id1, $subscription->subscriptionId()); + self::assertSame($this->id1, $subscription->id()); self::assertSame(1, $subscription->version()); self::assertTrue($subscription->starting()); self::assertFalse($subscription->paused()); @@ -202,7 +202,7 @@ public function testStatefulListener(): void { $this->listener9 ->expects(self::atLeastOnce()) - ->method('listenerId') + ->method('id') ->willReturn($this->id1) ; @@ -242,13 +242,13 @@ public function testStatefulListener(): void $subscription = new Subscription($this->listener9, $this->clock); self::assertSame($subscription->listener(), $this->listener9); - self::assertSame($this->id1, $subscription->subscriptionId()); + self::assertSame($this->id1, $subscription->id()); self::assertSame(0, $subscription->version()); self::assertFalse($subscription->starting()); $subscription->startFor($this->event1); - self::assertSame($this->id1, $subscription->subscriptionId()); + self::assertSame($this->id1, $subscription->id()); self::assertSame(1, $subscription->version()); self::assertTrue($subscription->starting()); @@ -312,7 +312,7 @@ public function testListenerWithPicker(): void { $this->listener7 ->expects(self::atLeastOnce()) - ->method('listenerId') + ->method('id') ->willReturn($this->id1) ; $this->listener7 @@ -327,12 +327,12 @@ public function testListenerWithPicker(): void $subscription = new Subscription($this->listener7, $this->clock); self::assertSame($subscription->listener(), $this->listener7); - self::assertSame($this->id1, $subscription->subscriptionId()); + self::assertSame($this->id1, $subscription->id()); self::assertSame(0, $subscription->version()); $subscription->startFor($this->event3); - self::assertSame($this->id1, $subscription->subscriptionId()); + self::assertSame($this->id1, $subscription->id()); self::assertSame(1, $subscription->version()); $this->stream1 = new InMemoryStream($this->event1, $this->event2, $this->event3); @@ -386,14 +386,14 @@ public function testListenerWithFilterer(): void $this->listener8 ->expects(self::atLeastOnce()) - ->method('listenerId') + ->method('id') ->willReturn($this->id1) ; $subscription = new Subscription($this->listener8, $this->clock); self::assertSame($subscription->listener(), $this->listener8); - self::assertSame($this->id1, $subscription->subscriptionId()); + self::assertSame($this->id1, $subscription->id()); self::assertSame(0, $subscription->version()); $subscription->startFor($this->event2); @@ -450,7 +450,7 @@ public function testTransactionalListenerWithoutReplaying(): void { $this->listener3 ->expects(self::atLeastOnce()) - ->method('listenerId') + ->method('id') ->willReturn($this->id1) ; $this->listener1 @@ -461,12 +461,12 @@ public function testTransactionalListenerWithoutReplaying(): void $subscription = new Subscription($this->listener3, $this->clock); self::assertSame($subscription->listener(), $this->listener3); - self::assertSame($this->id1, $subscription->subscriptionId()); + self::assertSame($this->id1, $subscription->id()); self::assertSame(0, $subscription->version()); $subscription->startFor($this->event1); - self::assertSame($this->id1, $subscription->subscriptionId()); + self::assertSame($this->id1, $subscription->id()); self::assertSame(1, $subscription->version()); $this->stream1 = new InMemoryStream($this->event1, $this->event2); @@ -536,21 +536,21 @@ public function testCompletingListener(): void { $this->listener3 ->expects(self::atLeastOnce()) - ->method('listenerId') + ->method('id') ->willReturn($this->id1) ; $subscription = new Subscription($this->listener3, $this->clock); self::assertSame($subscription->listener(), $this->listener3); - self::assertSame($this->id1, $subscription->subscriptionId()); + self::assertSame($this->id1, $subscription->id()); self::assertSame(0, $subscription->version()); self::assertFalse($subscription->completed()); self::assertFalse($subscription->paused()); $subscription->startFor($this->event1); - self::assertSame($this->id1, $subscription->subscriptionId()); + self::assertSame($this->id1, $subscription->id()); self::assertSame(1, $subscription->version()); self::assertFalse($subscription->completed()); self::assertFalse($subscription->paused()); @@ -647,14 +647,14 @@ public function testStartingAlreadyStartedSubscription(): void { $this->listener1 ->expects(self::atLeastOnce()) - ->method('listenerId') + ->method('id') ->willReturn($this->id1) ; $subscription = new Subscription($this->listener1, $this->clock); self::assertSame($subscription->listener(), $this->listener1); - self::assertSame($this->id1, $subscription->subscriptionId()); + self::assertSame($this->id1, $subscription->id()); $subscription->startFor($this->event1); @@ -667,7 +667,7 @@ public function testStartingStatefulSubscription(): void { $this->listener9 ->expects(self::atLeastOnce()) - ->method('listenerId') + ->method('id') ->willReturn($this->id1) ; $this->listener9 @@ -679,7 +679,7 @@ public function testStartingStatefulSubscription(): void $subscription = new Subscription($this->listener9, $this->clock); self::assertSame($subscription->listener(), $this->listener9); - self::assertSame($this->id1, $subscription->subscriptionId()); + self::assertSame($this->id1, $subscription->id()); $subscription->startFor($this->event1); } @@ -688,14 +688,14 @@ public function testNotStartedListener(): void { $this->listener1 ->expects(self::atLeastOnce()) - ->method('listenerId') + ->method('id') ->willReturn($this->id1) ; $subscription = new Subscription($this->listener1, $this->clock); self::assertSame($subscription->listener(), $this->listener1); - self::assertSame($this->id1, $subscription->subscriptionId()); + self::assertSame($this->id1, $subscription->id()); $this->store ->expects(self::never()) @@ -718,7 +718,7 @@ public function testRestartingSubscription(): void { $this->listener4 ->expects(self::atLeastOnce()) - ->method('listenerId') + ->method('id') ->willReturn($this->id1) ; $this->listener4 @@ -729,12 +729,12 @@ public function testRestartingSubscription(): void $subscription = new Subscription($this->listener4, $this->clock); self::assertSame($subscription->listener(), $this->listener4); - self::assertSame($this->id1, $subscription->subscriptionId()); + self::assertSame($this->id1, $subscription->id()); self::assertSame(0, $subscription->version()); $subscription->startFor($this->event1); - self::assertSame($this->id1, $subscription->subscriptionId()); + self::assertSame($this->id1, $subscription->id()); self::assertSame(1, $subscription->version()); $this->stream1 = new InMemoryStream($this->event1, $this->event2); @@ -783,14 +783,14 @@ public function testRestartingNotStartedSubscription(): void { $this->listener1 ->expects(self::atLeastOnce()) - ->method('listenerId') + ->method('id') ->willReturn($this->id1) ; $subscription = new Subscription($this->listener1, $this->clock); self::assertSame($subscription->listener(), $this->listener1); - self::assertSame($this->id1, $subscription->subscriptionId()); + self::assertSame($this->id1, $subscription->id()); $this->expectExceptionObject(new Event\Subscription\Exception\SubscriptionNotStartedYet($subscription)); @@ -801,19 +801,19 @@ public function testRestartingCompletedSubscription(): void { $this->listener3 ->expects(self::atLeastOnce()) - ->method('listenerId') + ->method('id') ->willReturn($this->id1) ; $subscription = new Subscription($this->listener3, $this->clock); self::assertSame($subscription->listener(), $this->listener3); - self::assertSame($this->id1, $subscription->subscriptionId()); + self::assertSame($this->id1, $subscription->id()); self::assertSame(0, $subscription->version()); $subscription->startFor($this->event1); - self::assertSame($this->id1, $subscription->subscriptionId()); + self::assertSame($this->id1, $subscription->id()); self::assertSame(1, $subscription->version()); $this->stream1 = new InMemoryStream($this->event1, $this->event2); @@ -888,19 +888,19 @@ public function testRestartingNonResettableListener(): void { $this->listener1 ->expects(self::atLeastOnce()) - ->method('listenerId') + ->method('id') ->willReturn($this->id1) ; $subscription = new Subscription($this->listener1, $this->clock); self::assertSame($subscription->listener(), $this->listener1); - self::assertSame($this->id1, $subscription->subscriptionId()); + self::assertSame($this->id1, $subscription->id()); self::assertSame(0, $subscription->version()); $subscription->startFor($this->event1); - self::assertSame($this->id1, $subscription->subscriptionId()); + self::assertSame($this->id1, $subscription->id()); self::assertSame(1, $subscription->version()); $this->stream1 = new InMemoryStream($this->event1, $this->event2); @@ -969,13 +969,13 @@ public function testNonPositiveLimitGivenWhileSubscribingToTheEventStoreAfterSta { $this->listener1 ->expects(self::atLeastOnce()) - ->method('listenerId') + ->method('id') ->with() ->willReturn($this->id1) ; $subscription = new Subscription($this->listener1, $this->clock); - self::assertSame($this->id1, $subscription->subscriptionId()); + self::assertSame($this->id1, $subscription->id()); $subscription->startFor($this->event1); $this->store @@ -1002,7 +1002,7 @@ public function testContinuousListeningWithNumberOfEventsBeingExactlyImposedLimi { $this->listener1 ->expects(self::atLeastOnce()) - ->method('listenerId') + ->method('id') ->willReturn($this->id1) ; $this->listener1 @@ -1013,12 +1013,12 @@ public function testContinuousListeningWithNumberOfEventsBeingExactlyImposedLimi $subscription = new Subscription($this->listener1, $this->clock); self::assertSame($subscription->listener(), $this->listener1); - self::assertSame($this->id1, $subscription->subscriptionId()); + self::assertSame($this->id1, $subscription->id()); self::assertSame(0, $subscription->version()); $subscription->startFor($this->event1); - self::assertSame($this->id1, $subscription->subscriptionId()); + self::assertSame($this->id1, $subscription->id()); self::assertSame(1, $subscription->version()); $this->stream1 = new InMemoryStream($this->event1, $this->event2); @@ -1069,7 +1069,7 @@ public function testContinuousListeningWithNumberOfEventsBeingMoreThanImposedLim { $this->listener1 ->expects(self::atLeastOnce()) - ->method('listenerId') + ->method('id') ->willReturn($this->id1) ; $this->listener1 @@ -1080,12 +1080,12 @@ public function testContinuousListeningWithNumberOfEventsBeingMoreThanImposedLim $subscription = new Subscription($this->listener1, $this->clock); self::assertSame($subscription->listener(), $this->listener1); - self::assertSame($this->id1, $subscription->subscriptionId()); + self::assertSame($this->id1, $subscription->id()); self::assertSame(0, $subscription->version()); $subscription->startFor($this->event1); - self::assertSame($this->id1, $subscription->subscriptionId()); + self::assertSame($this->id1, $subscription->id()); self::assertSame(1, $subscription->version()); $this->stream1 = new InMemoryStream($this->event1, $this->event2); @@ -1132,7 +1132,7 @@ public function testContinuousListeningWithNumberOfEventsBeingMoreThanImposedLim { $this->listener1 ->expects(self::atLeastOnce()) - ->method('listenerId') + ->method('id') ->willReturn($this->id1) ; $this->listener1 @@ -1143,12 +1143,12 @@ public function testContinuousListeningWithNumberOfEventsBeingMoreThanImposedLim $subscription = new Subscription($this->listener1, $this->clock); self::assertSame($subscription->listener(), $this->listener1); - self::assertSame($this->id1, $subscription->subscriptionId()); + self::assertSame($this->id1, $subscription->id()); self::assertSame(0, $subscription->version()); $subscription->startFor($this->event1); - self::assertSame($this->id1, $subscription->subscriptionId()); + self::assertSame($this->id1, $subscription->id()); self::assertSame(1, $subscription->version()); $this->stream1 = new InMemoryStream($this->event1, $this->event2); @@ -1195,7 +1195,7 @@ public function testContinuousListeningWithNumberOfEventsBeingLessThanImposedLim { $this->listener1 ->expects(self::atLeastOnce()) - ->method('listenerId') + ->method('id') ->willReturn($this->id1) ; $this->listener1 @@ -1206,12 +1206,12 @@ public function testContinuousListeningWithNumberOfEventsBeingLessThanImposedLim $subscription = new Subscription($this->listener1, $this->clock); self::assertSame($subscription->listener(), $this->listener1); - self::assertSame($this->id1, $subscription->subscriptionId()); + self::assertSame($this->id1, $subscription->id()); self::assertSame(0, $subscription->version()); $subscription->startFor($this->event1); - self::assertSame($this->id1, $subscription->subscriptionId()); + self::assertSame($this->id1, $subscription->id()); self::assertSame(1, $subscription->version()); $this->stream1 = new InMemoryStream($this->event1, $this->event2); @@ -1262,19 +1262,19 @@ public function testCompletingListenerWhileContinuousListening(): void { $this->listener3 ->expects(self::atLeastOnce()) - ->method('listenerId') + ->method('id') ->willReturn($this->id1) ; $subscription = new Subscription($this->listener3, $this->clock); self::assertSame($subscription->listener(), $this->listener3); - self::assertSame($this->id1, $subscription->subscriptionId()); + self::assertSame($this->id1, $subscription->id()); self::assertSame(0, $subscription->version()); $subscription->startFor($this->event1); - self::assertSame($this->id1, $subscription->subscriptionId()); + self::assertSame($this->id1, $subscription->id()); self::assertSame(1, $subscription->version()); $this->stream1 = new InMemoryStream($this->event1, $this->event2); diff --git a/tests/Infrastructure/Domain/Event/Subscription/DbalTransactionalSubscriptionTest.php b/tests/Infrastructure/Domain/Event/Subscription/DbalTransactionalSubscriptionTest.php index ae48c7cd..f9aa85d3 100644 --- a/tests/Infrastructure/Domain/Event/Subscription/DbalTransactionalSubscriptionTest.php +++ b/tests/Infrastructure/Domain/Event/Subscription/DbalTransactionalSubscriptionTest.php @@ -128,12 +128,12 @@ public function testObject(): void $this->subscription ->expects(self::once()) - ->method('subscriptionId') + ->method('id') ->with() ->willReturn($this->subscriptionId) ; - self::assertSame($this->subscriptionId, $subscription->subscriptionId()); + self::assertSame($this->subscriptionId, $subscription->id()); $this->subscription ->expects(self::once()) diff --git a/tests/Infrastructure/Domain/Event/Subscription/EventSourcedRepositoryTest.php b/tests/Infrastructure/Domain/Event/Subscription/EventSourcedRepositoryTest.php index d5dcd4f5..825f7883 100644 --- a/tests/Infrastructure/Domain/Event/Subscription/EventSourcedRepositoryTest.php +++ b/tests/Infrastructure/Domain/Event/Subscription/EventSourcedRepositoryTest.php @@ -84,13 +84,13 @@ protected function setUp(): void $this->nonEventSourcedSubscription3 = $this->getMockBuilder(DecoratedSubscription::class)->setMockClassName('nonEventSourcedSubscription3')->getMock(); $this->nonEventSourcedSubscription3->method('subscription')->willReturn($this->nonEventSourcedSubscription2); - $this->id1 = new class('f5e65690-e50d-4312-a175-b004ec1bd42a') extends Domain\Id\UUID implements Listener\Id { + $this->id1 = new class ('f5e65690-e50d-4312-a175-b004ec1bd42a') extends Domain\Id\UUID implements Listener\Id { }; - $this->id2 = new class('d01286b0-7dd6-4520-b714-0e9903ab39af') extends Domain\Id\UUID implements Listener\Id { + $this->id2 = new class ('d01286b0-7dd6-4520-b714-0e9903ab39af') extends Domain\Id\UUID implements Listener\Id { }; - $this->id3 = new class('39ab6175-7cd7-4c94-95c1-03d05c2e2fa2') extends Domain\Id\UUID implements Listener\Id { + $this->id3 = new class ('39ab6175-7cd7-4c94-95c1-03d05c2e2fa2') extends Domain\Id\UUID implements Listener\Id { }; - $this->id4 = new class('2d40c01d-7aa9-4757-ac28-de3733431cc5') extends Domain\Id\UUID implements Listener\Id { + $this->id4 = new class ('2d40c01d-7aa9-4757-ac28-de3733431cc5') extends Domain\Id\UUID implements Listener\Id { }; $this->event1 = Event\Envelope::new($this->getMockBuilder(Event::class)->setMockClassName('event1')->getMockForAbstractClass(), UUID::random()); @@ -153,7 +153,7 @@ public function testFindingNotExistingSubscription(): void $this->eventSourcedSubscription1 ->expects(self::once()) - ->method('producerId') + ->method('id') ->willReturn($this->id1) ; @@ -177,7 +177,7 @@ public function testCheckingForExistingSubscription(): void $this->eventSourcedSubscription1 ->expects(self::once()) - ->method('producerId') + ->method('id') ->willReturn($this->id1) ; @@ -192,7 +192,7 @@ public function testCheckingForNotExistingSubscription(): void $this->eventSourcedSubscription1 ->expects(self::once()) - ->method('producerId') + ->method('id') ->willReturn($this->id1) ; @@ -232,7 +232,7 @@ public function testFindingSubscription(): void $this->eventSourcedSubscription1 ->expects(self::once()) - ->method('producerId') + ->method('id') ->willReturn($this->id1) ; @@ -288,7 +288,7 @@ public function testFindingPreviouslyRestartedSubscription(): void $this->eventSourcedSubscription1 ->expects(self::once()) - ->method('producerId') + ->method('id') ->willReturn($this->id1) ; @@ -324,7 +324,7 @@ public function testAddingEventSourcedSubscription(): void $this->eventSourcedSubscription1 ->expects(self::atLeastOnce()) - ->method('producerId') + ->method('id') ->willReturn($this->id1) ; @@ -339,7 +339,7 @@ public function testAddingDecoratedEventSourcedSubscription(): void $this->eventSourcedSubscription1 ->expects(self::atLeastOnce()) - ->method('producerId') + ->method('id') ->willReturn($this->id1) ; @@ -413,7 +413,7 @@ public function testFindingSubscriptions(): void use Streak\Domain\Event; -abstract class EventSourcedSubscription implements Event\Subscription, Event\Sourced +abstract class EventSourcedSubscription implements Event\Sourced\Subscription { } diff --git a/tests/Infrastructure/Domain/Event/Subscription/LazyLoadedSubscriptionTest.php b/tests/Infrastructure/Domain/Event/Subscription/LazyLoadedSubscriptionTest.php index 65a0cacc..65fb4e43 100644 --- a/tests/Infrastructure/Domain/Event/Subscription/LazyLoadedSubscriptionTest.php +++ b/tests/Infrastructure/Domain/Event/Subscription/LazyLoadedSubscriptionTest.php @@ -64,7 +64,7 @@ public function testObject(): void ->willReturn($this->subscription) ; - self::assertSame($this->id, $subscription->subscriptionId()); + self::assertSame($this->id, $subscription->id()); $this->subscription ->expects(self::once()) diff --git a/tests/Infrastructure/Domain/EventStore/EventStoreTestCase.php b/tests/Infrastructure/Domain/EventStore/EventStoreTestCase.php index 7fdfee20..d262107b 100644 --- a/tests/Infrastructure/Domain/EventStore/EventStoreTestCase.php +++ b/tests/Infrastructure/Domain/EventStore/EventStoreTestCase.php @@ -317,7 +317,7 @@ public function testItGetsEvent(): void $uuid2 = new Id\UUID('5e04364e-4590-403b-9f8f-3ae14f6dcce6'); $event = new EventStoreTestCase\Event1(); - $event = new Event\Envelope($uuid1, 'event1', $event, new EventStoreTestCase\ProducerId1('producer1'), 1); + $event = new Event\Envelope($uuid1, 'event1', $event, new EventStoreTestCase\ProducerId1('producer1'), new EventStoreTestCase\ProducerId1('producer1'), 1); $this->store->add($event); @@ -334,11 +334,8 @@ abstract protected function newEventStore(): EventStore; abstract class ValueId implements Domain\Id { - private string $value; - - public function __construct(string $value) + public function __construct(private string $value) { - $this->value = $value; } public function equals(object $id): bool diff --git a/tests/Infrastructure/Domain/UnitOfWork/EventStoreUnitOfWorkTest.php b/tests/Infrastructure/Domain/UnitOfWork/EventStoreUnitOfWorkTest.php index 82cb5091..0746ad6d 100644 --- a/tests/Infrastructure/Domain/UnitOfWork/EventStoreUnitOfWorkTest.php +++ b/tests/Infrastructure/Domain/UnitOfWork/EventStoreUnitOfWorkTest.php @@ -18,9 +18,9 @@ use Streak\Domain\EventStore; use Streak\Domain\Exception\ConcurrentWriteDetected; use Streak\Domain\Id\UUID; +use Streak\Infrastructure\Domain\EventStoreUnitOfWorkTest\NonVersionableEventSourcedStub; +use Streak\Infrastructure\Domain\EventStoreUnitOfWorkTest\VersionableEventSourcedStub; use Streak\Infrastructure\Domain\UnitOfWork\Exception\ObjectNotSupported; -use Streak\Infrastructure\Domain\UnitOfWorkTest\NonVersionableEventSourcedStub; -use Streak\Infrastructure\Domain\UnitOfWorkTest\VersionableEventSourcedStub; /** * @author Alan Gabriel Bem @@ -69,7 +69,7 @@ public function testObject(): void $uow = new EventStoreUnitOfWork($this->store); self::assertEmpty($uow->uncommitted()); - self::assertEquals(0, $uow->count()); + self::assertSame(0, $uow->count()); self::assertFalse($uow->has($object1)); self::assertFalse($uow->has($object2)); self::assertFalse($uow->has($object3)); @@ -78,7 +78,7 @@ public function testObject(): void $uow->remove($object1); self::assertEmpty($uow->uncommitted()); - self::assertEquals(0, $uow->count()); + self::assertSame(0, $uow->count()); self::assertFalse($uow->has($object1)); self::assertFalse($uow->has($object2)); self::assertFalse($uow->has($object3)); @@ -87,7 +87,7 @@ public function testObject(): void $uow->add($object1); self::assertSame([$object1], $uow->uncommitted()); - self::assertEquals(1, $uow->count()); + self::assertSame(1, $uow->count()); self::assertTrue($uow->has($object1)); self::assertFalse($uow->has($object2)); self::assertFalse($uow->has($object3)); @@ -96,7 +96,7 @@ public function testObject(): void $uow->add($object2); self::assertSame([$object1, $object2], $uow->uncommitted()); - self::assertEquals(2, $uow->count()); + self::assertSame(2, $uow->count()); self::assertTrue($uow->has($object1)); self::assertTrue($uow->has($object2)); self::assertFalse($uow->has($object3)); @@ -105,7 +105,7 @@ public function testObject(): void $uow->remove($object2); self::assertSame([$object1], $uow->uncommitted()); - self::assertEquals(1, $uow->count()); + self::assertSame(1, $uow->count()); self::assertTrue($uow->has($object1)); self::assertFalse($uow->has($object2)); self::assertFalse($uow->has($object3)); @@ -114,7 +114,7 @@ public function testObject(): void $uow->add($object3); self::assertSame([$object1, $object3], $uow->uncommitted()); - self::assertEquals(2, $uow->count()); + self::assertSame(2, $uow->count()); self::assertTrue($uow->has($object1)); self::assertFalse($uow->has($object2)); self::assertTrue($uow->has($object3)); @@ -123,7 +123,7 @@ public function testObject(): void $uow->add($object4); self::assertSame([$object1, $object3, $object4], $uow->uncommitted()); - self::assertEquals(3, $uow->count()); + self::assertSame(3, $uow->count()); self::assertTrue($uow->has($object1)); self::assertFalse($uow->has($object2)); self::assertTrue($uow->has($object3)); @@ -159,7 +159,7 @@ public function testObject(): void self::assertTrue($object1->commited()); self::assertFalse($object2->commited()); self::assertTrue($object3->commited()); - self::assertEquals(0, $uow->count()); + self::assertSame(0, $uow->count()); self::assertFalse($uow->has($object1)); self::assertFalse($uow->has($object2)); self::assertFalse($uow->has($object3)); @@ -246,7 +246,7 @@ public function testError(): void // retry try { iterator_to_array($uow->commit()); - } catch (\RuntimeException $exception3) { + } catch (\RuntimeException) { self::fail(); } finally { self::assertSame(0, $uow->count()); @@ -259,7 +259,7 @@ public function testError(): void try { iterator_to_array($uow->commit()); self::fail(); - } catch (ConcurrentWriteDetected $exception4) { + } catch (ConcurrentWriteDetected) { self::assertSame(0, $uow->count()); self::assertFalse($uow->has($object1)); self::assertFalse($uow->has($object2)); @@ -282,23 +282,19 @@ public function testWrongObject(): void } } -namespace Streak\Infrastructure\Domain\UnitOfWorkTest; +namespace Streak\Infrastructure\Domain\EventStoreUnitOfWorkTest; use Streak\Domain; use Streak\Domain\Event; use Streak\Domain\Versionable; -class VersionableEventSourcedStub implements Event\Sourced, Versionable +class VersionableEventSourcedStub implements Event\Producer, Event\Consumer, Event\Replayable, Versionable { - private Domain\Id $id; - private int $version; private array $events; private bool $commited = false; - public function __construct(Domain\Id $id, int $version, Event\Envelope ...$events) + public function __construct(private Domain\Id $id, private int $version, Event\Envelope ...$events) { - $this->id = $id; - $this->version = $version; $this->events = $events; } @@ -307,12 +303,7 @@ public function equals(object $object): bool throw new \BadMethodCallException(); } - public function lastReplayed(): ?Event\Envelope - { - throw new \BadMethodCallException(); - } - - public function producerId(): Domain\Id + public function id(): Domain\Id { return $this->id; } @@ -327,6 +318,16 @@ public function replay(Event\Stream $events): void throw new \BadMethodCallException(); } + public function lastEvent(): ?Event\Envelope + { + throw new \BadMethodCallException(); + } + + public function applyEvent(Event\Envelope $event): void + { + throw new \BadMethodCallException(); + } + public function version(): int { return $this->version; @@ -343,14 +344,12 @@ public function commited(): bool } } -class NonVersionableEventSourcedStub implements Event\Sourced +class NonVersionableEventSourcedStub implements Event\Producer, Event\Consumer, Event\Replayable { - private Domain\Id $id; private array $events; - public function __construct(Domain\Id $id, Event\Envelope ...$events) + public function __construct(private Domain\Id $id, Event\Envelope ...$events) { - $this->id = $id; $this->events = $events; } @@ -359,14 +358,14 @@ public function equals(object $object): bool throw new \BadMethodCallException(); } - public function lastReplayed(): ?Event\Envelope + public function id(): Domain\Id { - throw new \BadMethodCallException(); + return $this->id; } - public function producerId(): Domain\Id + public function applyEvent(Event\Envelope $event): void { - return $this->id; + throw new \BadMethodCallException(); } public function events(): array diff --git a/tests/Infrastructure/Domain/UnitOfWork/Exception/ObjectNotSupportedTest.php b/tests/Infrastructure/Domain/UnitOfWork/Exception/ObjectNotSupportedTest.php index 866cb0b5..65d0a1e3 100644 --- a/tests/Infrastructure/Domain/UnitOfWork/Exception/ObjectNotSupportedTest.php +++ b/tests/Infrastructure/Domain/UnitOfWork/Exception/ObjectNotSupportedTest.php @@ -27,6 +27,6 @@ public function testIt(): void $exception = new ObjectNotSupported($object, $previous); self::assertSame($object, $exception->object()); self::assertSame($previous, $exception->getPrevious()); - self::assertEquals('Object is not supported.', $exception->getMessage()); + self::assertSame('Object is not supported.', $exception->getMessage()); } } diff --git a/tests/Infrastructure/Domain/UnitOfWork/SnapshottingUnitOfWorkTest.php b/tests/Infrastructure/Domain/UnitOfWork/SnapshottingUnitOfWorkTest.php index 2e8d4830..6ea17054 100644 --- a/tests/Infrastructure/Domain/UnitOfWork/SnapshottingUnitOfWorkTest.php +++ b/tests/Infrastructure/Domain/UnitOfWork/SnapshottingUnitOfWorkTest.php @@ -15,6 +15,7 @@ use InvalidArgumentException; use PHPUnit\Framework\TestCase; +use Streak\Domain\AggregateRoot; use Streak\Domain\Event; use Streak\Infrastructure\Domain\AggregateRoot\Snapshotter; use Streak\Infrastructure\Domain\UnitOfWork; @@ -34,11 +35,11 @@ class SnapshottingUnitOfWorkTest extends TestCase private Event\Sourced\AggregateRoot $aggregateRoot1; - private Event\Sourced\AggregateRoot\Id $aggregateRootId1; + private AggregateRoot\Id $aggregateRootId1; private Event\Sourced\AggregateRoot $aggregateRoot2; - private Event\Sourced\AggregateRoot\Id $aggregateRootId2; + private AggregateRoot\Id $aggregateRootId2; protected function setUp(): void { @@ -46,9 +47,9 @@ protected function setUp(): void $this->snapshotter = $this->getMockBuilder(Snapshotter::class)->getMockForAbstractClass(); $this->producer = $this->getMockBuilder(Event\Producer::class)->setMockClassName('s__producer')->getMockForAbstractClass(); $this->aggregateRoot1 = $this->getMockBuilder(Event\Sourced\AggregateRoot::class)->setMockClassName('s__ar1')->getMockForAbstractClass(); - $this->aggregateRootId1 = $this->getMockBuilder(Event\Sourced\AggregateRoot\Id::class)->getMockForAbstractClass(); + $this->aggregateRootId1 = $this->getMockBuilder(AggregateRoot\Id::class)->getMockForAbstractClass(); $this->aggregateRoot2 = $this->getMockBuilder(Event\Sourced\AggregateRoot::class)->setMockClassName('s__ar2')->getMockForAbstractClass(); - $this->aggregateRootId2 = $this->getMockBuilder(Event\Sourced\AggregateRoot\Id::class)->getMockForAbstractClass(); + $this->aggregateRootId2 = $this->getMockBuilder(AggregateRoot\Id::class)->getMockForAbstractClass(); } public function testObject(): void @@ -57,12 +58,12 @@ public function testObject(): void $this->producer ->expects(self::never()) // we do not handle this type of object - ->method('producerId') + ->method('id') ; $this->aggregateRoot1 ->expects(self::atLeastOnce()) - ->method('producerId') + ->method('id') ->willReturn($this->aggregateRootId1) ; @@ -78,7 +79,7 @@ public function testObject(): void $this->aggregateRoot2 ->expects(self::atLeastOnce()) - ->method('producerId') + ->method('id') ->willReturn($this->aggregateRootId2) ; @@ -237,7 +238,7 @@ public function testCommitInterval(int $beforeVersion, int $afterVersion, int $s $this->aggregateRoot1 ->expects(self::atLeastOnce()) - ->method('producerId') + ->method('id') ->willReturn($this->aggregateRootId1) ; @@ -276,7 +277,7 @@ public function commitIntervalProvider(): array */ public function testItDoesNotCreateWithWrongInterval(int $interval): void { - self::expectException(InvalidArgumentException::class); + $this->expectException(InvalidArgumentException::class); new SnapshottingUnitOfWork($this->uow, $this->snapshotter, 0); } diff --git a/tests/Infrastructure/Domain/UnitOfWork/SubscriptionDAOUnitOfWorkTest.php b/tests/Infrastructure/Domain/UnitOfWork/SubscriptionDAOUnitOfWorkTest.php index f310a5d1..c5437792 100644 --- a/tests/Infrastructure/Domain/UnitOfWork/SubscriptionDAOUnitOfWorkTest.php +++ b/tests/Infrastructure/Domain/UnitOfWork/SubscriptionDAOUnitOfWorkTest.php @@ -54,14 +54,14 @@ public function testItAddsDecorator(): void public function testItDoesNotAddsNotSupportedSubscription(): void { $subscription = $this->getMockBuilder(Subscription::class)->getMock(); - self::expectException(ObjectNotSupported::class); + $this->expectException(ObjectNotSupported::class); $this->uow->add($subscription); } public function testHasOnNotSupportedObject(): void { $subscription = $this->getMockBuilder(Subscription::class)->getMock(); - self::expectException(ObjectNotSupported::class); + $this->expectException(ObjectNotSupported::class); $this->uow->has($subscription); } @@ -69,11 +69,11 @@ public function testItRemoves(): void { $subscription = $this->createSubscriptionStub('1'); $this->uow->add($subscription); - self::assertEquals(1, $this->uow->count()); + self::assertSame(1, $this->uow->count()); $this->uow->remove($subscription); self::assertFalse($this->uow->has($subscription)); self::assertEmpty($this->uow->uncommitted()); - self::assertEquals(0, $this->uow->count()); + self::assertSame(0, $this->uow->count()); } public function testItRemovesNonExistedSubscription(): void @@ -87,7 +87,7 @@ public function testItRemovesNonExistedSubscription(): void public function testItDoesNotRemoveNotSupportedSubscription(): void { $subscription = $this->getMockBuilder(Subscription::class)->getMock(); - self::expectException(ObjectNotSupported::class); + $this->expectException(ObjectNotSupported::class); $this->uow->remove($subscription); } @@ -106,7 +106,7 @@ public function testItCommitsWithException(): void $subscription = $this->createSubscriptionStub('1'); $this->uow->add($subscription); $this->dao->expects(self::once())->method('save')->with($subscription)->willThrowException(new \Exception()); - self::expectException(\Exception::class); + $this->expectException(\Exception::class); iterator_to_array($this->uow->commit()); self::assertEquals([$subscription], $this->uow->uncommitted()); } @@ -118,7 +118,7 @@ private function createSubscriptionDecoratorStub(string $id): Subscription\Decor { $result = $this->getMockBuilder(DecoratedSubscription::class)->getMock(); $result->method('subscription')->willReturn($this->createSubscriptionStub($id)); - $result->method('subscriptionId')->willReturn($this->createIdStub($id)); + $result->method('id')->willReturn($this->createIdStub($id)); return $result; } @@ -129,7 +129,7 @@ private function createSubscriptionDecoratorStub(string $id): Subscription\Decor private function createSubscriptionStub(string $id): DAO\Subscription { $result = $this->getMockBuilder(DAO\Subscription::class)->disableOriginalConstructor()->getMock(); - $result->method('subscriptionId')->willReturn($this->createIdStub($id)); + $result->method('id')->willReturn($this->createIdStub($id)); return $result; } diff --git a/tests/Infrastructure/Serializer/PhpSerializerTest.php b/tests/Infrastructure/Serializer/PhpSerializerTest.php index 300c447e..26ef4acb 100644 --- a/tests/Infrastructure/Serializer/PhpSerializerTest.php +++ b/tests/Infrastructure/Serializer/PhpSerializerTest.php @@ -34,7 +34,7 @@ public function testSerialize($value): void $serialized = $serializer->serialize($value); $unserialized = $serializer->unserialize($serialized); - self::assertEquals(serialize($value), $serialized); + self::assertSame(serialize($value), $serialized); self::assertEquals(unserialize($serialized), $unserialized); self::assertEquals($value, $unserialized); }