Completed
Push — master ( 4803b3...959101 )
by Frank
03:46
created

AggregateRootTestCase::pointInTime()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 4
ccs 2
cts 2
cp 1
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 0
crap 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\EventSourcing\Time\Clock;
9
use EventSauce\EventSourcing\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
     * @var AggregateRootId
55
     */
56
    private $aggregateRootId;
57
58
    /**
59
     * @before
60
     */
61 6
    protected function setUpEventStore()
62
    {
63 6
        $className = $this->aggregateRootClassName();
64 6
        $this->clock = new TestClock();
65 6
        $this->aggregateRootId = AggregateRootId::create();
66 6
        $this->messageRepository = new InMemoryMessageRepository($this->messageDispatcher());
67 6
        $this->repository = new AggregateRootRepository($className, $this->messageRepository, new DelegatingMessageDecorator());
68 6
        $this->commandHandler = $this->commandHandler($this->repository, $this->clock);
69 6
        $this->expectedEvents = [];
70 6
        $this->assertedScenario = false;
71 6
        $this->theExpectedException = null;
72 6
        $this->caughtException = null;
73 6
    }
74
75
    /**
76
     * @after
77
     */
78 6
    protected function assertScenario()
79
    {
80
        // @codeCoverageIgnoreStart
81
        if ($this->assertedScenario) {
82
            return;
83
        }
84
        // @codeCoverageIgnoreEnd
85
86
        try {
87 6
            $this->assertExpectedException($this->theExpectedException, $this->caughtException);
88 4
            $this->assertLastCommitEqualsEvents(... $this->expectedEvents);
89 4
            $this->messageRepository->purgeLastCommit();
90 4
        } finally {
91 6
            $this->assertedScenario = true;
92 6
            $this->theExpectedException = null;
93 6
            $this->caughtException = null;
94
        }
95 4
    }
96
97
    abstract protected function aggregateRootClassName(): string;
98
99
    abstract protected function commandHandler(AggregateRootRepository $repository, Clock $clock): CommandHandler;
100
101 6
    protected function aggregateRootId(): AggregateRootId
102
    {
103 6
        return $this->aggregateRootId;
104
    }
105
106
    /**
107
     * @return $this
108
     */
109 1
    protected function given(Event ... $events)
110
    {
111 1
        $this->repository->persistEvents(... $events);
112 1
        $this->messageRepository->purgeLastCommit();
113
114 1
        return $this;
115
    }
116
117
    /**
118
     * @return $this
119
     */
120 6
    protected function when(Command $command)
121
    {
122
        try {
123 6
            $this->commandHandler->handle($command);
124 3
        } catch (Exception $exception) {
125 3
            $this->caughtException = $exception;
126
        }
127
128 6
        return $this;
129
    }
130
131
    /**
132
     * @return $this
133
     */
134 2
    protected function then(Event ... $events)
135
    {
136 2
        $this->expectedEvents = $events;
137
138 2
        return $this;
139
    }
140
141
    /**
142
     * @return $this
143
     */
144 2
    public function thenWeAreSorry(Exception $expectedException)
145
    {
146 2
        $this->theExpectedException = $expectedException;
147
148 2
        return $this;
149
    }
150
151
    /**
152
     * @return $this
153
     */
154 1
    protected function thenNothingShouldHaveHappened()
155
    {
156 1
        $this->expectedEvents = [];
157
158 1
        return $this;
159
    }
160
161 4
    protected function assertLastCommitEqualsEvents(Event ... $events)
162
    {
163 4
        self::assertEquals($events, $this->messageRepository->lastCommit(), "Events are not equal.");
164 4
    }
165
166 6
    private function assertExpectedException(Exception $expectedException = null, Exception $caughtException = null)
167
    {
168 6
        if ($expectedException == $caughtException) {
169 3
            return;
170
        }
171
172 3
        if ($expectedException == null || ($caughtException !== null && (get_class($expectedException) !== get_class($caughtException)))) {
173 2
            throw $caughtException;
174
        }
175
176 1
        self::assertEquals([$expectedException], [$caughtException], ">> Exceptions are not equal.");
177 1
    }
178
179 2
    protected function pointInTime(): PointInTime
180
    {
181 2
        return $this->clock->pointInTime();
182
    }
183
184 6
    protected function messageDispatcher(): MessageDispatcher
185
    {
186 6
        return new SynchronousMessageDispatcher(... $this->consumers());
187
    }
188
189
    /**
190
     * @return Consumer[]
191
     */
192 6
    protected function consumers(): array
193
    {
194 6
        return [];
195
    }
196
}