Passed
Pull Request — master (#84)
by Frank
07:12
created

MessageConsumerTestCase::expectToFail()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 2
c 1
b 0
f 0
nc 1
nop 1
dl 0
loc 5
rs 10
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(...$eventsOrMessages)
62
    {
63
        $this->processMessages($eventsOrMessages);
64
65
        return $this;
66
    }
67
68
    /**
69
     * @return $this
70
     */
71
    public function when(...$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
    protected function processMessages(array $eventsOrMessages): void
93
    {
94
        $messages = $this->ensureEventsAreMessages($eventsOrMessages);
95
96
        foreach ($messages as $message) {
97
            $this->messageConsumer->handle($message);
98
        }
99
    }
100
101
    /**
102
     * @return Message[]
103
     */
104
    private function ensureEventsAreMessages(array $events): array
105
    {
106
        return array_map(function (object $event) {
107
            return $event instanceof Message ? $event : new Message($event);
108
        }, $events);
109
    }
110
111
    /**
112
     * @after
113
     *
114
     * @throws Exception
115
     */
116
    protected function assertScenario(): void
117
    {
118
        // @codeCoverageIgnoreStart
119
        if ($this->assertedScenario) {
120
            return;
121
        }
122
        // @codeCoverageIgnoreEnd
123
124
        $this->assertedScenario = true;
125
126
        $this->assertExpectedException($this->theExpectedException, $this->caughtException);
127
128
        if (is_callable($this->assertionCallback)) {
129
            ($this->assertionCallback)($this->messageConsumer);
130
        }
131
    }
132
133
    /**
134
     * @return $this
135
     */
136
    public function then(callable $assertion)
137
    {
138
        $this->assertionCallback = $assertion;
139
140
        return $this;
141
    }
142
143
    private function assertExpectedException(
144
        Exception $expectedException = null,
145
        Exception $caughtException = null
146
    ): void {
147
        if (null !== $caughtException && (null === $expectedException || get_class($expectedException) !== get_class(
148
                    $caughtException
149
                ))) {
150
            throw $caughtException;
151
        }
152
153
        self::assertEquals([$expectedException], [$caughtException], '>> Exceptions are not equal.');
154
    }
155
}
156