Passed
Pull Request — master (#84)
by Frank
17:17 queued 07:16
created

MessageConsumerTestCase   A

Complexity

Total Complexity 18

Size/Duplication

Total Lines 145
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 18
eloc 36
c 1
b 0
f 0
dl 0
loc 145
rs 10

10 Methods

Rating   Name   Duplication   Size   Complexity  
A unsetMessageConsumer() 0 3 1
A given() 0 5 1
A expectToFail() 0 5 1
A when() 0 9 2
A setupMessageConsumer() 0 4 1
A processMessages() 0 6 2
A assertScenario() 0 14 3
A ensureEventsAreMessages() 0 5 2
A then() 0 5 1
A assertExpectedException() 0 11 4
1
<?php
2
3
declare(strict_types=1);
4
5
namespace EventSauce\EventSourcing\TestUtilities;
6
7
use EventSauce\EventSourcing\Message;
8
use EventSauce\EventSourcing\MessageConsumer;
9
use Exception;
10
use PHPUnit\Framework\TestCase;
11
12
abstract class MessageConsumerTestCase extends TestCase
13
{
14
    /**
15
     * @var MessageConsumer
16
     */
17
    protected $messageConsumer;
18
19
    /**
20
     * @var Exception|null
21
     */
22
    private $caughtException;
23
24
    /**
25
     * @var Exception|null
26
     */
27
    private $theExpectedException;
28
29
    /**
30
     * @var bool
31
     */
32
    private $assertedScenario = false;
33
34
    /**
35
     * @var callable
36
     */
37
    private $assertionCallback;
38
39
    abstract public function messageConsumer(): MessageConsumer;
40
41
    /**
42
     * @before
43
     */
44
    public function setupMessageConsumer(): void
45
    {
46
        $this->messageConsumer = $this->messageConsumer();
47
        $this->assertedScenario = false;
48
    }
49
50
    /**
51
     * @before
52
     */
53
    public function unsetMessageConsumer(): void
54
    {
55
        unset($this->messageConsumer);
56
    }
57
58
    /**
59
     * @return $this
60
     */
61
    protected function given(object ...$eventsOrMessages)
62
    {
63
        $this->processMessages($eventsOrMessages);
64
65
        return $this;
66
    }
67
68
    /**
69
     * @return $this
70
     */
71
    public function when(object ...$eventsOrMessages)
72
    {
73
        try {
74
            $this->processMessages($eventsOrMessages);
75
        } catch (Exception $exception) {
76
            $this->caughtException = $exception;
77
        }
78
79
        return $this;
80
    }
81
82
    /**
83
     * @return $this
84
     */
85
    public function expectToFail(Exception $expectedException)
86
    {
87
        $this->theExpectedException = $expectedException;
88
89
        return $this;
90
    }
91
92
    /**
93
     * @param object[] $eventsOrMessages
94
     */
95
    protected function processMessages(array $eventsOrMessages): void
96
    {
97
        $messages = $this->ensureEventsAreMessages($eventsOrMessages);
98
99
        foreach ($messages as $message) {
100
            $this->messageConsumer->handle($message);
101
        }
102
    }
103
104
    /**
105
     * @return Message[]
106
     */
107
    private function ensureEventsAreMessages(array $events): array
108
    {
109
        return array_map(function (object $event) {
110
            return $event instanceof Message ? $event : new Message($event);
111
        }, $events);
112
    }
113
114
    /**
115
     * @after
116
     *
117
     * @throws Exception
118
     */
119
    protected function assertScenario(): void
120
    {
121
        // @codeCoverageIgnoreStart
122
        if ($this->assertedScenario) {
123
            return;
124
        }
125
        // @codeCoverageIgnoreEnd
126
127
        $this->assertedScenario = true;
128
129
        $this->assertExpectedException($this->theExpectedException, $this->caughtException);
130
131
        if (is_callable($this->assertionCallback)) {
132
            ($this->assertionCallback)($this->messageConsumer);
133
        }
134
    }
135
136
    /**
137
     * @return $this
138
     */
139
    public function then(callable $assertion)
140
    {
141
        $this->assertionCallback = $assertion;
142
143
        return $this;
144
    }
145
146
    private function assertExpectedException(
147
        Exception $expectedException = null,
148
        Exception $caughtException = null
149
    ): void {
150
        if (null !== $caughtException && (null === $expectedException || get_class($expectedException) !== get_class(
151
                    $caughtException
152
                ))) {
153
            throw $caughtException;
154
        }
155
156
        self::assertEquals([$expectedException], [$caughtException], '>> Exceptions are not equal.');
157
    }
158
}
159