Completed
Push — master ( 0592b8...007274 )
by Frank
02:18
created

AggregateRootTestCase::commandHandler()

Size

Total Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 1
ccs 0
cts 0
cp 0
c 0
b 0
f 0
nc 1
1
<?php
2
3
namespace EventSauce\EventSourcing;
4
5
use Exception;
6
use function get_class;
7
use PHPUnit\Framework\TestCase;
8
use EventSauce\Time\Clock;
9
use EventSauce\Time\TestClock;
10
11
abstract class AggregateRootTestCase extends TestCase
12
{
13
    /**
14
     * @var InMemoryMessageRepository
15
     */
16
    private $messageRepository;
17
18
    /**
19
     * @var AggregateRootRepository
20
     */
21
    private $repository;
22
23
    /**
24
     * @var CommandHandler
25
     */
26
    private $commandHandler;
27
28
    /**
29
     * @var Exception|null
30
     */
31
    private $caughtException;
32
33
    /**
34
     * @var Event[]
35
     */
36
    private $expectedEvents = [];
37
38
    /**
39
     * @var Exception|null
40
     */
41
    private $theExpectedException;
42
43
    /**
44
     * @var TestClock
45
     */
46
    private $clock;
47
48
    /**
49
     * @var bool
50
     */
51
    private $assertedScenario = false;
52
53
    /**
54
     * @before
55
     */
56 5
    protected function setUpEventStore()
57
    {
58 5
        $className = $this->aggregateRootClassName();
59 5
        $this->clock = new TestClock();
60 5
        $this->messageRepository = new InMemoryMessageRepository($this->messageDispatcher());
61 5
        $this->repository = new AggregateRootRepository($className, $this->messageRepository, new DelegatingMessageDecorator());
62 5
        $this->commandHandler = $this->commandHandler($this->repository, $this->clock);
63 5
        $this->expectedEvents = [];
64 5
        $this->assertedScenario = false;
65 5
        $this->theExpectedException = null;
66 5
        $this->caughtException = null;
67 5
    }
68
69
    /**
70
     * @after
71
     */
72 5
    protected function assertScenario()
73
    {
74
        // @codeCoverageIgnoreStart
75
        if ($this->assertedScenario) {
76
            return;
77
        }
78
        // @codeCoverageIgnoreEnd
79
80 5
        $this->assertExpectedException($this->theExpectedException, $this->caughtException);
81 5
        $this->assertLastCommitEqualsEvents(... $this->expectedEvents);
82 5
        $this->messageRepository->purgeLastCommit();
83 5
        $this->assertedScenario = true;
84 5
    }
85
86
    abstract protected function aggregateRootClassName(): string;
87
88
    abstract protected function commandHandler(AggregateRootRepository $repository, Clock $clock): CommandHandler;
89
90
    /**
91
     * @return $this
92
     */
93 1
    protected function given(Event ... $events)
94
    {
95 1
        $this->repository->persist(... $events);
96 1
        $this->messageRepository->purgeLastCommit();
97
98 1
        return $this;
99
    }
100
101
    /**
102
     * @return $this
103
     */
104 5
    protected function when(Command $command)
105
    {
106
        try {
107 5
            $this->commandHandler->handle($command);
108 2
        } catch (Exception $exception) {
109 2
            $this->caughtException = $exception;
110
        }
111
112 5
        return $this;
113
    }
114
115
    /**
116
     * @return $this
117
     */
118 2
    protected function then(Event ... $events)
119
    {
120 2
        $this->expectedEvents = $events;
121
122 2
        return $this;
123
    }
124
125
    /**
126
     * @return $this
127
     */
128 1
    public function thenWeAreSorry(Exception $expectedException)
129
    {
130 1
        $this->theExpectedException = $expectedException;
131
132 1
        return $this;
133
    }
134
135
    /**
136
     * @return $this
137
     */
138 1
    protected function thenNothingShouldHaveHappened()
139
    {
140 1
        $this->expectedEvents = [];
141
142 1
        return $this;
143
    }
144
145 5
    protected function assertLastCommitEqualsEvents(Event ... $events)
146
    {
147 5
        self::assertEquals($events, $this->messageRepository->lastCommit());
148 5
    }
149
150 5
    private function assertExpectedException(Exception $expectedException = null, Exception $caughtException = null)
151
    {
152 5
        $this->theExpectedException = null;
153 5
        $this->caughtException = null;
154
155 5
        if ($expectedException == $caughtException) {
156 4
            return;
157
        }
158
159 2
        if ($expectedException === null || get_class($expectedException) !== get_class($caughtException)) {
160 1
            throw $caughtException;
161
        }
162
163 1
        self::assertEquals([$expectedException], [$caughtException]);
164 1
    }
165
166 2
    protected function pointInTime(): PointInTime
167
    {
168 2
        return $this->clock->pointInTime();
169
    }
170
171 5
    private function messageDispatcher(): MessageDispatcher
172
    {
173 5
        return new SynchronousMessageDispatcher(... $this->consumers());
174
    }
175
176 5
    private function consumers(): array
177
    {
178 5
        return [];
179
    }
180
}