Skip to content

Commit

Permalink
Merge pull request #1 from patchlevel/add-aggregate-tests
Browse files Browse the repository at this point in the history
add aggregate tests
  • Loading branch information
DavidBadura authored Nov 21, 2020
2 parents 1578808 + 1183262 commit 9c7d7b3
Show file tree
Hide file tree
Showing 21 changed files with 650 additions and 19 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/phpstan.yml
Original file line number Diff line number Diff line change
Expand Up @@ -56,4 +56,4 @@ jobs:
run: "composer install --no-interaction --no-progress --no-suggest"

- name: "PHPStan"
run: "vendor/bin/phpstan analyse -l max src --memory-limit=-1"
run: "vendor/bin/phpstan analyse"
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ coverage/
phpunit.xml
.phpunit.result.cache
.php_cs.cache
phpstan.neon
31 changes: 31 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
help: ## shows this help
@awk 'BEGIN {FS = ":.*?## "} /^[a-zA-Z_\-\.]+:.*?## / {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}' $(MAKEFILE_LIST)

.PHONY: php-cs-check
php-cs-check: ## run cs fixer (dry-run)
vendor/bin/php-cs-fixer fix --diff --dry-run

.PHONY: php-cs-fix
php-cs-fix: ## run cs fixer
vendor/bin/php-cs-fixer fix

.PHONY: phpstan
phpstan: ## run phpstan static code analyser
vendor/bin/phpstan analyse

.PHONY: psalm
psalm: ## run psalm static code analyser
vendor/bin/psalm

.PHONY: phpunit
phpunit: ## run phpunit tests
vendor/bin/phpunit --testdox --colors=always -v $(OPTIONS)

.PHONY: static
static: php-cs-fix phpstan psalm ## run static analyser

.PHONY: test
test: phpunit ## run tests

.PHONY: dev
dev: static test ## run dev tools
1 change: 1 addition & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
"friendsofphp/php-cs-fixer": "^2.16.7",
"phpstan/phpstan": "^0.12.54",
"phpunit/phpunit": "^9.4.3",
"symfony/var-dumper": "^5.1",
"vimeo/psalm": "^4.1.1"
},
"config": {
Expand Down
90 changes: 89 additions & 1 deletion composer.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions phpstan.neon.dist
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
parameters:
level: max
paths:
- src
4 changes: 2 additions & 2 deletions phpunit.xml.dist
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit bootstrap="tests/bootstrap.php" colors="true">
<testsuites>
<testsuite name="test">
<directory>./tests</directory>
<testsuite name="unit">
<directory>./tests/Unit</directory>
</testsuite>
</testsuites>
<filter>
Expand Down
8 changes: 4 additions & 4 deletions src/Aggregate/AggregateChanged.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
namespace Patchlevel\EventSourcing\Aggregate;

use DateTimeImmutable;
use InvalidArgumentException;
use function get_class;
use function json_decode;
use function json_encode;
Expand Down Expand Up @@ -55,8 +54,9 @@ public function payload(): array

/**
* @param array<string, mixed> $payload
* @return static
*/
public static function occur(string $aggregateId, array $payload = []): self
protected static function occur(string $aggregateId, array $payload = []): self
{
return new static($aggregateId, $payload);
}
Expand All @@ -79,7 +79,7 @@ public static function deserialize(array $data): self
$class = $data['event'];

if (!is_subclass_of($class, self::class)) {
throw new InvalidArgumentException();
throw new AggregateException();
}

/** @var array<string, mixed> $payload */
Expand All @@ -102,7 +102,7 @@ public function serialize(): array
'playhead' => $this->playhead,
'event' => get_class($this),
'payload' => json_encode($this->payload, JSON_THROW_ON_ERROR),
'recordedOn' => $this->recordedOn instanceof DateTimeImmutable ? $this->recordedOn->format('Y-m-d H:i:s') : null,
'recordedOn' => $this->recordedOn instanceof DateTimeImmutable ? $this->recordedOn->format(DateTimeImmutable::ATOM) : null,
];
}
}
9 changes: 9 additions & 0 deletions src/Aggregate/AggregateException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?php declare(strict_types=1);

namespace Patchlevel\EventSourcing\Aggregate;

use RuntimeException;

class AggregateException extends RuntimeException
{
}
2 changes: 1 addition & 1 deletion src/Aggregate/AggregateRoot.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ abstract class AggregateRoot

abstract public function aggregateRootId(): string;

public function apply(AggregateChanged $event): void
protected function apply(AggregateChanged $event): void
{
$this->playhead++;
$event = $event->recordNow($this->playhead);
Expand Down
22 changes: 12 additions & 10 deletions src/Repository/Repository.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ final class Repository
private EventStream $eventStream;

/**
* @var class-string
* @psalm-var class-string
*/
private string $aggregateClass;

Expand All @@ -31,6 +31,9 @@ final class Repository
*/
private array $instances = [];

/**
* @psalm-param class-string $aggregateClass
*/
public function __construct(
Store $store,
EventStream $eventStream,
Expand All @@ -55,7 +58,7 @@ public function load(string $id): AggregateRoot
throw new AggregateNotFoundException($this->aggregateClass, $id);
}

return $this->instances[$id] = $this->createAggregate($this->aggregateClass, $events);
return $this->instances[$id] = $this->createAggregate($events);
}

public function has(string $id): bool
Expand Down Expand Up @@ -87,26 +90,25 @@ public function save(AggregateRoot $aggregate): void
}

/**
* @psalm-assert class-string $class
* @psalm-assert class-string<AggregateRoot> $class
*/
private function assertExtendsEventSourcedAggregateRoot(string $class): void
{
if (!class_exists($class)) {
throw new InvalidArgumentException(sprintf('class "%s" not found', $class));
}

if (is_subclass_of($class, AggregateRoot::class) === false) {
throw new InvalidArgumentException(sprintf("Class '%s' is not an EventSourcedAggregateRoot.", $class));
}
}

/**
* @param class-string $class
* @param array<AggregateChanged> $eventStream
*/
private function createAggregate(string $class, array $eventStream): AggregateRoot
private function createAggregate(array $eventStream): AggregateRoot
{
if (!class_exists($class)) {
throw new InvalidArgumentException(sprintf('class "%s" not found', $class));
}

$reflectionClass = new ReflectionClass($class);
$reflectionClass = new ReflectionClass($this->aggregateClass);

/** @var AggregateRoot $aggregate */
$aggregate = $reflectionClass->newInstanceWithoutConstructor();
Expand Down
Loading

0 comments on commit 9c7d7b3

Please sign in to comment.