Completed
Push — master ( 469bd2...690756 )
by Frank
03:49
created

AggregateRootTestCase::when()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 10
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 2

Importance

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