AMQPBackendDispatcherTest   A
last analyzed

Complexity

Total Complexity 16

Size/Duplication

Total Lines 186
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 2

Importance

Changes 0
Metric Value
wmc 16
c 0
b 0
f 0
lcom 1
cbo 2
dl 0
loc 186
rs 10

13 Methods

Rating   Name   Duplication   Size   Complexity  
A setUp() 0 9 2
A testThrowIfSettingsMissFactoryClassOptionOnGetContext() 0 8 1
A testThrowIfFactoryClassIsNotRealClass() 0 8 1
A testThrowIfFactoryClassIsNotInstanceOfAmqpConnectionFactoryInterface() 0 8 1
A testShouldPassExpectedOptionsToAmqpConnectionFactoryConstructor() 0 26 1
A testShouldReturnExpectedAmqpContext() 0 24 1
A testQueue() 0 10 1
A testDefaultQueue() 0 7 1
A testDefaultQueueNotFound() 0 9 1
A testInvalidQueue() 0 11 1
A testAllQueueInitializeOnce() 0 22 2
A getDispatcher() 0 12 1
A getMockQueue() 0 17 2
1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * This file is part of the Sonata Project package.
7
 *
8
 * (c) Thomas Rabaix <[email protected]>
9
 *
10
 * For the full copyright and license information, please view the LICENSE
11
 * file that was distributed with this source code.
12
 */
13
14
namespace Sonata\NotificationBundle\Tests\Backend;
15
16
use Enqueue\AmqpLib\AmqpConnectionFactory;
17
use Interop\Amqp\AmqpContext;
18
use PHPUnit\Framework\MockObject\MockObject;
19
use PHPUnit\Framework\TestCase;
20
use Sonata\NotificationBundle\Backend\AMQPBackend;
21
use Sonata\NotificationBundle\Backend\AMQPBackendDispatcher;
22
use Sonata\NotificationBundle\Exception\BackendNotFoundException;
23
use Sonata\NotificationBundle\Tests\Mock\AmqpConnectionFactoryStub;
24
25
class AMQPBackendDispatcherTest extends TestCase
26
{
27
    protected function setUp(): void
28
    {
29
        if (!class_exists(AmqpConnectionFactory::class)) {
30
            $this->markTestSkipped('enqueue/amqp-lib library is not installed');
31
        }
32
33
        AmqpConnectionFactoryStub::$config = null;
34
        AmqpConnectionFactoryStub::$context = null;
35
    }
36
37
    public function testThrowIfSettingsMissFactoryClassOptionOnGetContext(): void
38
    {
39
        $dispatcher = new AMQPBackendDispatcher([], [], 'default', []);
40
41
        $this->expectException(\LogicException::class);
42
        $this->expectExceptionMessage('The factory_class option is missing though it is required.');
43
        $dispatcher->getContext();
44
    }
45
46
    public function testThrowIfFactoryClassIsNotRealClass(): void
47
    {
48
        $dispatcher = new AMQPBackendDispatcher(['factory_class' => 'anInvalidClass'], [], 'default', []);
49
50
        $this->expectException(\LogicException::class);
51
        $this->expectExceptionMessage('The factory_class option "anInvalidClass" has to be valid class that implements "Interop\Amqp\AmqpConnectionFactory"');
52
        $dispatcher->getContext();
53
    }
54
55
    public function testThrowIfFactoryClassIsNotInstanceOfAmqpConnectionFactoryInterface(): void
56
    {
57
        $dispatcher = new AMQPBackendDispatcher(['factory_class' => \stdClass::class], [], 'default', []);
58
59
        $this->expectException(\LogicException::class);
60
        $this->expectExceptionMessage('The factory_class option "stdClass" has to be valid class that implements "Interop\Amqp\AmqpConnectionFactory"');
61
        $dispatcher->getContext();
62
    }
63
64
    public function testShouldPassExpectedOptionsToAmqpConnectionFactoryConstructor(): void
65
    {
66
        $dispatcher = new AMQPBackendDispatcher(
67
            [
68
                'host' => 'theHost',
69
                'port' => 'thePort',
70
                'user' => 'theUser',
71
                'pass' => 'thePass',
72
                'vhost' => 'theVhost',
73
                'factory_class' => AmqpConnectionFactoryStub::class,
74
            ],
75
            [],
76
            'default',
77
            []
78
        );
79
80
        $dispatcher->getContext();
81
82
        $this->assertSame([
83
            'host' => 'theHost',
84
            'port' => 'thePort',
85
            'user' => 'theUser',
86
            'pass' => 'thePass',
87
            'vhost' => 'theVhost',
88
        ], AmqpConnectionFactoryStub::$config);
89
    }
90
91
    public function testShouldReturnExpectedAmqpContext(): void
92
    {
93
        $expectedContext = $this->createMock(AmqpContext::class);
94
95
        $dispatcher = new AMQPBackendDispatcher(
96
            [
97
                'host' => 'aHost',
98
                'port' => 'aPort',
99
                'user' => 'aUser',
100
                'pass' => 'aPass',
101
                'vhost' => 'aVhost',
102
                'factory_class' => AmqpConnectionFactoryStub::class,
103
            ],
104
            [],
105
            'default',
106
            []
107
        );
108
109
        AmqpConnectionFactoryStub::$context = $expectedContext;
110
111
        $actualContext = $dispatcher->getContext();
112
113
        $this->assertSame($expectedContext, $actualContext);
114
    }
115
116
    public function testQueue(): void
117
    {
118
        $mock = $this->getMockQueue('foo', 'message.type.foo', $this->once());
119
        $mock2 = $this->getMockQueue('bar', 'message.type.foo', $this->never());
120
        $fooBackend = ['type' => 'message.type.foo', 'backend' => $mock];
121
        $barBackend = ['type' => 'message.type.bar', 'backend' => $mock2];
122
        $backends = [$fooBackend, $barBackend];
123
        $dispatcher = $this->getDispatcher($backends);
124
        $dispatcher->createAndPublish('message.type.foo', []);
125
    }
126
127
    public function testDefaultQueue(): void
128
    {
129
        $mock = $this->getMockQueue('foo', 'message.type.foo', $this->once());
130
        $fooBackend = ['type' => 'default', 'backend' => $mock];
131
        $dispatcher = $this->getDispatcher([$fooBackend]);
132
        $dispatcher->createAndPublish('some.other.type', []);
133
    }
134
135
    public function testDefaultQueueNotFound(): void
136
    {
137
        $mock = $this->getMockQueue('foo', 'message.type.foo', $this->never());
138
        $fooBackend = ['type' => 'message.type.foo', 'backend' => $mock];
139
        $dispatcher = $this->getDispatcher([$fooBackend]);
140
141
        $this->expectException(BackendNotFoundException::class);
142
        $dispatcher->createAndPublish('some.other.type', []);
143
    }
144
145
    public function testInvalidQueue(): void
146
    {
147
        $mock = $this->getMockQueue('foo', 'message.type.bar');
148
        $dispatcher = $this->getDispatcher(
149
            [['type' => 'bar', 'backend' => $mock]],
150
            [['queue' => 'foo', 'routing_key' => 'message.type.bar']]
151
        );
152
153
        $this->expectException(BackendNotFoundException::class);
154
        $dispatcher->createAndPublish('message.type.bar', []);
155
    }
156
157
    public function testAllQueueInitializeOnce(): void
158
    {
159
        $queues = [
160
            ['queue' => 'foo', 'routing_key' => 'message.type.foo'],
161
            ['queue' => 'bar', 'routing_key' => 'message.type.bar'],
162
            ['queue' => 'baz', 'routing_key' => 'message.type.baz'],
163
        ];
164
165
        $backends = [];
166
167
        foreach ($queues as $queue) {
168
            $mock = $this->getMockQueue($queue['queue'], $queue['routing_key']);
169
            $mock->expects($this->once())
170
                ->method('initialize');
171
            $backends[] = ['type' => $queue['routing_key'], 'backend' => $mock];
172
        }
173
174
        $dispatcher = $this->getDispatcher($backends, $queues);
175
176
        $dispatcher->createAndPublish('message.type.foo', []);
177
        $dispatcher->createAndPublish('message.type.foo', []);
178
    }
179
180
    protected function getDispatcher(array $backends, array $queues = [['queue' => 'foo', 'routing_key' => 'message.type.foo']]): AMQPBackendDispatcher
181
    {
182
        $settings = [
183
                'host' => 'foo',
184
                'port' => 'port',
185
                'user' => 'user',
186
                'pass' => 'pass',
187
                'vhost' => '/',
188
        ];
189
190
        return new AMQPBackendDispatcher($settings, $queues, 'default', $backends);
191
    }
192
193
    private function getMockQueue($queue, $type, $called = null): MockObject
194
    {
195
        $methods = ['createAndPublish', 'initialize'];
196
        $args = ['', 'foo', false, 'message.type.foo'];
197
        $mock = $this->getMockBuilder(AMQPBackend::class)
198
                     ->setConstructorArgs($args)
199
                     ->setMethods($methods)
200
                     ->getMock();
201
202
        if (null !== $called) {
203
            $mock->expects($called)
204
                ->method('createAndPublish')
205
            ;
206
        }
207
208
        return $mock;
209
    }
210
}
211