Skip to content

Commit 7fbdfaa

Browse files
authored
Merge pull request #24 from patchlevel/enable-mocks
Enable PHPUnit mocks in tests
2 parents 28c9002 + bd89382 commit 7fbdfaa

4 files changed

Lines changed: 78 additions & 62 deletions

File tree

src/Test/AggregateRootTestCase.php

Lines changed: 46 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,12 @@ abstract class AggregateRootTestCase extends TestCase
2828

2929
/** @var array<mixed> */
3030
private array $parameters = [];
31+
private object|null $aggregate = null;
3132

3233
/** @var array<object|Closure> */
3334
private array $thenExpectations = [];
3435

36+
private Throwable|null $thrownException = null;
3537
/** @var class-string<Throwable>|null */
3638
private string|null $expectedException = null;
3739
private string|null $expectedExceptionMessage = null;
@@ -41,6 +43,7 @@ abstract protected function aggregateClass(): string;
4143

4244
final public function given(object ...$events): self
4345
{
46+
$this->aggregate = null;
4447
$this->givenEvents = $events;
4548

4649
return $this;
@@ -52,6 +55,42 @@ final public function when(object $callable, mixed ...$parameters): self
5255
$this->when = $callable;
5356
$this->parameters = $parameters;
5457

58+
if ($this->givenEvents) {
59+
$this->aggregate = $this->aggregateClass()::createFromEvents($this->givenEvents);
60+
}
61+
62+
try {
63+
$callableOrCommand = $this->when;
64+
$return = null;
65+
66+
if ($callableOrCommand instanceof Closure) {
67+
/** @var AggregateRoot|null $return */
68+
$return = $callableOrCommand($this->aggregate);
69+
} else {
70+
foreach (HandlerFinder::findInClass($this->aggregateClass()) as $handler) {
71+
if (!$callableOrCommand instanceof $handler->commandClass) {
72+
continue;
73+
}
74+
75+
$reflection = new ReflectionClass($this->aggregateClass());
76+
$reflectionMethod = $reflection->getMethod($handler->method);
77+
78+
/** @var AggregateRoot|null $return */
79+
$return = $reflectionMethod->invokeArgs($handler->static ? null : $this->aggregate, [$callableOrCommand, ...$this->parameters]);
80+
}
81+
}
82+
83+
if ($this->aggregate !== null && $return instanceof AggregateRoot) {
84+
throw new AggregateAlreadySet();
85+
}
86+
87+
if ($this->aggregate === null) {
88+
$this->aggregate = $return;
89+
}
90+
} catch (Throwable $throwable) {
91+
$this->thrownException = $throwable;
92+
}
93+
5594
return $this;
5695
}
5796

@@ -89,60 +128,28 @@ final public function assert(): self
89128
throw new NoWhenProvided();
90129
}
91130

92-
$aggregate = null;
93-
94-
if ($this->givenEvents) {
95-
$aggregate = $this->aggregateClass()::createFromEvents($this->givenEvents);
96-
}
97-
98-
try {
99-
$callableOrCommand = $this->when;
100-
$return = null;
101-
102-
if ($callableOrCommand instanceof Closure) {
103-
$return = $callableOrCommand($aggregate);
104-
} else {
105-
foreach (HandlerFinder::findInClass($this->aggregateClass()) as $handler) {
106-
if (!$callableOrCommand instanceof $handler->commandClass) {
107-
continue;
108-
}
109-
110-
$reflection = new ReflectionClass($this->aggregateClass());
111-
$reflectionMethod = $reflection->getMethod($handler->method);
112-
113-
$return = $reflectionMethod->invokeArgs($handler->static ? null : $aggregate, [$callableOrCommand, ...$this->parameters]);
114-
}
115-
}
116-
117-
if ($aggregate !== null && $return instanceof AggregateRoot) {
118-
throw new AggregateAlreadySet();
119-
}
120-
121-
if ($aggregate === null) {
122-
$aggregate = $return;
123-
}
124-
} catch (Throwable $throwable) {
125-
$this->handleException($throwable);
131+
if ($this->thrownException !== null) {
132+
$this->handleException($this->thrownException);
126133

127134
return $this;
128135
}
129136

130137
$this->expectedExceptionWasNotThrown();
131138

132-
if (!$aggregate instanceof AggregateRoot) {
139+
if (!$this->aggregate instanceof AggregateRoot) {
133140
throw new NoAggregateCreated();
134141
}
135142

136143
$expectedEvents = array_values(array_filter($this->thenExpectations, static fn (object $item) => !$item instanceof Closure));
137144
$expectationCallbacks = array_filter($this->thenExpectations, static fn (object $item) => $item instanceof Closure);
138145

139-
$events = $aggregate->releaseEvents();
146+
$events = $this->aggregate->releaseEvents();
140147

141148
self::assertEquals($expectedEvents, $events, 'The events doesn\'t match the expected events.');
142149

143150
foreach ($expectationCallbacks as $callback) {
144151
try {
145-
$callback($aggregate);
152+
$callback($this->aggregate);
146153
} catch (Throwable $t) {
147154
$reflection = new ReflectionFunction($callback);
148155

@@ -169,6 +176,8 @@ final public function reset(): void
169176
$this->thenExpectations = [];
170177
$this->expectedException = null;
171178
$this->expectedExceptionMessage = null;
179+
$this->aggregate = null;
180+
$this->thrownException = null;
172181
}
173182

174183
private function handleException(Throwable $throwable): void

tests/Unit/Fixture/Notifier.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Patchlevel\EventSourcing\PhpUnit\Tests\Unit\Fixture;
6+
7+
interface Notifier
8+
{
9+
public function notify(): void;
10+
}

tests/Unit/Fixture/Profile.php

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,11 +33,15 @@ public function emitsNoEvents(): void
3333
}
3434

3535
#[Handle]
36-
public static function createProfile(CreateProfile $createProfile): self
36+
public static function createProfile(CreateProfile $createProfile, Notifier|null $notifier = null): self
3737
{
3838
$self = new self();
3939
$self->recordThat(new ProfileCreated($createProfile->id, $createProfile->email));
4040

41+
if ($notifier) {
42+
$notifier->notify();
43+
}
44+
4145
return $self;
4246
}
4347

tests/Unit/Test/AggregateRootTestCaseTest.php

Lines changed: 17 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
use Patchlevel\EventSourcing\PhpUnit\Tests\Unit\Fixture\CreateProfile;
1414
use Patchlevel\EventSourcing\PhpUnit\Tests\Unit\Fixture\CreateProfileWithFailure;
1515
use Patchlevel\EventSourcing\PhpUnit\Tests\Unit\Fixture\Email;
16+
use Patchlevel\EventSourcing\PhpUnit\Tests\Unit\Fixture\Notifier;
1617
use Patchlevel\EventSourcing\PhpUnit\Tests\Unit\Fixture\Profile;
1718
use Patchlevel\EventSourcing\PhpUnit\Tests\Unit\Fixture\ProfileCreated;
1819
use Patchlevel\EventSourcing\PhpUnit\Tests\Unit\Fixture\ProfileError;
@@ -232,29 +233,6 @@ public function testVisited(): void
232233
self::assertSame(1, $test::getCount());
233234
}
234235

235-
public function testVisitedDoubleAssert(): void
236-
{
237-
$test = $this->getTester();
238-
239-
$test
240-
->given(
241-
new ProfileCreated(
242-
ProfileId::fromString('1'),
243-
Email::fromString('hq@patchlevel.de'),
244-
),
245-
)
246-
->when(
247-
static fn (Profile $profile) => $profile->visitProfile(new VisitProfile(ProfileId::fromString('2'))),
248-
)
249-
->then(
250-
new ProfileVisited(ProfileId::fromString('2')),
251-
);
252-
253-
$test->assert();
254-
$test->assert();
255-
self::assertSame(2, $test::getCount());
256-
}
257-
258236
public function testCreation(): void
259237
{
260238
$test = $this->getTester();
@@ -310,7 +288,7 @@ public function testNoGivenAndNoCreation(): void
310288

311289
$test
312290
->when(
313-
static fn () => 'no aggregate as return',
291+
static fn () => null,
314292
)
315293
->then(
316294
new ProfileVisited(ProfileId::fromString('2')),
@@ -344,6 +322,21 @@ public function testDoubleAggregateCreation(): void
344322
self::assertSame(1, $test::getCount());
345323
}
346324

325+
public function testCreationWithMock(): void
326+
{
327+
$test = $this->getTester();
328+
329+
$notifier = $this->createMock(Notifier::class);
330+
$notifier->expects($this->once())->method('notify');
331+
332+
$test
333+
->when(new CreateProfile(ProfileId::fromString('1'), Email::fromString('hq@patchlevel.de')), $notifier)
334+
->then(new ProfileCreated(ProfileId::fromString('1'), Email::fromString('hq@patchlevel.de')));
335+
336+
$test->assert();
337+
self::assertSame(1, $test::getCount());
338+
}
339+
347340
public function testReset(): void
348341
{
349342
$test = $this->getTester();

0 commit comments

Comments
 (0)