Passed
Push — master ( 79bf3c...52a24b )
by Alex
01:04 queued 13s
created

testInvokeWillThrowServiceNotCreatedExceptionIfTheStringConfigurationCannotBeFound()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 48
Code Lines 34

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 34
c 1
b 0
f 0
dl 0
loc 48
rs 9.376
cc 1
nc 1
nop 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace ArpTest\LaminasDoctrine\Factory\Service\EntityManager;
6
7
use Arp\LaminasDoctrine\Config\EntityManagerConfigs;
8
use Arp\LaminasDoctrine\Factory\Service\EntityManager\EntityManagerFactory;
9
use Arp\LaminasDoctrine\Service\Configuration\ConfigurationManagerInterface;
10
use Arp\LaminasDoctrine\Service\Configuration\Exception\ConfigurationManagerException;
11
use Arp\LaminasDoctrine\Service\Connection\ConnectionManagerInterface;
12
use Arp\LaminasDoctrine\Service\Connection\Exception\ConnectionManagerException;
13
use Doctrine\DBAL\Connection;
14
use Doctrine\ORM\Configuration;
15
use Laminas\ServiceManager\Exception\ServiceNotCreatedException;
16
use Laminas\ServiceManager\Exception\ServiceNotFoundException;
17
use PHPUnit\Framework\MockObject\MockObject;
18
use PHPUnit\Framework\TestCase;
19
use Psr\Container\ContainerExceptionInterface;
20
use Psr\Container\ContainerInterface;
21
22
/**
23
 * @covers  \Arp\LaminasDoctrine\Factory\Service\EntityManager\EntityManagerFactory
24
 *
25
 * @author  Alex Patterson <[email protected]>
26
 * @package ArpTest\LaminasDoctrine\Factory\Service
27
 */
28
final class EntityManagerFactoryTest extends TestCase
29
{
30
    /**
31
     * @var ContainerInterface&MockObject
32
     */
33
    private $container;
34
35
    /**
36
     * @var EntityManagerConfigs&MockObject
37
     */
38
    private $entityManagerConfigs;
39
40
    /**
41
     * @var ConfigurationManagerInterface&MockObject
42
     */
43
    private $configurationManager;
44
45
    /**
46
     * @var ConnectionManagerInterface&MockObject
47
     */
48
    private $connectionManager;
49
50
    /**
51
     * Prepare the test case dependencies
52
     */
53
    public function setUp(): void
54
    {
55
        $this->container = $this->createMock(ContainerInterface::class);
56
57
        $this->entityManagerConfigs = $this->createMock(EntityManagerConfigs::class);
58
59
        $this->configurationManager = $this->createMock(ConfigurationManagerInterface::class);
60
61
        $this->connectionManager = $this->createMock(ConnectionManagerInterface::class);
62
    }
63
64
    /**
65
     * Assert that factory is a callable instance
66
     */
67
    public function testIsInvokable(): void
68
    {
69
        $factory = new EntityManagerFactory();
70
71
        $this->assertIsCallable($factory);
72
    }
73
74
    /**
75
     * Assert a ServiceNotCreateException is thrown from __invoke() if the required 'configuration' configuration
76
     * option is missing or null
77
     *
78
     * @throws ServiceNotFoundException
79
     * @throws ContainerExceptionInterface
80
     */
81
    public function testInvokeWillThrowServiceNotCreatedExceptionIfTheRequiredConfigurationConfigIsMissing(): void
82
    {
83
        $factory = new EntityManagerFactory();
84
85
        $serviceName = 'doctrine.entitymanager.orm_default';
86
        $emConfig = [
87
            'connection' => 'FooConnectionName',
88
            // missing 'configuration' key
89
        ];
90
91
        $this->container->expects($this->once())
92
            ->method('get')
93
            ->with(EntityManagerConfigs::class)
94
            ->willReturn($this->entityManagerConfigs);
95
96
        $this->entityManagerConfigs->expects($this->once())
97
            ->method('getEntityManagerConfig')
98
            ->with($serviceName)
99
            ->willReturn($emConfig);
100
101
        $this->expectException(ServiceNotCreatedException::class);
102
        $this->expectExceptionMessage(
103
            sprintf(
104
                'The required \'configuration\' configuration option is missing for service \'%s\'',
105
                $serviceName
106
            )
107
        );
108
109
        $factory($this->container, $serviceName);
110
    }
111
112
    /**
113
     * Assert a ServiceNotCreateException is thrown from __invoke() if the required 'connection' configuration
114
     * option is missing or null
115
     *
116
     * @throws ServiceNotFoundException
117
     * @throws ContainerExceptionInterface
118
     */
119
    public function testInvokeWillThrowServiceNotCreatedExceptionIfTheRequiredConnectionConfigIsMissing(): void
120
    {
121
        $factory = new EntityManagerFactory();
122
123
        $serviceName = 'doctrine.entitymanager.orm_default';
124
        $emConfig = [
125
            'connection'    => null,
126
            'configuration' => 'BarConfigurationName',
127
        ];
128
129
        $this->container->expects($this->once())
130
            ->method('get')
131
            ->with(EntityManagerConfigs::class)
132
            ->willReturn($this->entityManagerConfigs);
133
134
        $this->entityManagerConfigs->expects($this->once())
135
            ->method('getEntityManagerConfig')
136
            ->with($serviceName)
137
            ->willReturn($emConfig);
138
139
        $this->expectException(ServiceNotCreatedException::class);
140
        $this->expectExceptionMessage(
141
            sprintf(
142
                'The required \'connection\' configuration option is missing for service \'%s\'',
143
                $serviceName
144
            )
145
        );
146
147
        $factory($this->container, $serviceName);
148
    }
149
150
    /**
151
     * Assert a ServiceNotCreateException is thrown from __invoke() if the required 'configuration' object
152
     * is of an invalid type
153
     *
154
     * @throws ServiceNotFoundException
155
     * @throws ContainerExceptionInterface
156
     */
157
    public function testInvokeWillThrowServiceNotCreatedExceptionIfTheRequiredConfigurationIsInvalid(): void
158
    {
159
        $factory = new EntityManagerFactory();
160
161
        $configuration = new \stdClass(); // invalid configuration class
162
        $serviceName = 'doctrine.entitymanager.orm_default';
163
        $emConfig = [
164
            'configuration' => $configuration,
165
            'connection'    => 'BarConnectionName',
166
        ];
167
168
        $this->container->expects($this->once())
169
            ->method('has')
170
            ->with(ConfigurationManagerInterface::class)
171
            ->willReturn(true);
172
173
        $this->container->expects($this->exactly(2))
174
            ->method('get')
175
            ->withConsecutive([EntityManagerConfigs::class], [ConfigurationManagerInterface::class])
176
            ->willReturnOnConsecutiveCalls($this->entityManagerConfigs, $this->configurationManager);
177
178
        $this->entityManagerConfigs->expects($this->once())
179
            ->method('getEntityManagerConfig')
180
            ->with($serviceName)
181
            ->willReturn($emConfig);
182
183
        $this->expectException(ServiceNotCreatedException::class);
184
        $this->expectExceptionMessage(
185
            sprintf(
186
                'The configuration must be an object of type \'%s\'; \'%s\' provided for service \'%s\'',
187
                Configuration::class,
188
                \stdClass::class,
189
                $serviceName
190
            )
191
        );
192
193
        $factory($this->container, $serviceName);
194
    }
195
196
    /**
197
     * Assert a ServiceNotCreateException is thrown from __invoke() if the required 'connection' object
198
     * is of an invalid type
199
     *
200
     * @throws ServiceNotFoundException
201
     * @throws ContainerExceptionInterface
202
     */
203
    public function testInvokeWillThrowServiceNotCreatedExceptionIfTheRequiredConnectionIsInvalid(): void
204
    {
205
        $factory = new EntityManagerFactory();
206
207
        $connection = new \stdClass(); // invalid configuration class
208
209
        /** @var Configuration|MockObject $configuration */
210
        $configuration = $this->createMock(Configuration::class);
211
212
        $serviceName = 'doctrine.entitymanager.orm_default';
213
        $emConfig = [
214
            'configuration' => $configuration,
215
            'connection'    => $connection,
216
        ];
217
218
        $this->container->expects($this->exactly(2))
219
            ->method('has')
220
            ->withConsecutive([ConfigurationManagerInterface::class], [ConnectionManagerInterface::class])
221
            ->willReturnOnConsecutiveCalls(true, true);
222
223
        $this->container->expects($this->exactly(3))
224
            ->method('get')
225
            ->withConsecutive(
226
                [EntityManagerConfigs::class],
227
                [ConfigurationManagerInterface::class],
228
                [ConnectionManagerInterface::class]
229
            )
230
            ->willReturnOnConsecutiveCalls(
231
                $this->entityManagerConfigs,
232
                $this->configurationManager,
233
                $this->connectionManager
234
            );
235
236
        $this->entityManagerConfigs->expects($this->once())
237
            ->method('getEntityManagerConfig')
238
            ->with($serviceName)
239
            ->willReturn($emConfig);
240
241
        $this->expectException(ServiceNotCreatedException::class);
242
        $this->expectExceptionMessage(
243
            sprintf(
244
                'The connection must be an object of type \'%s\'; \'%s\' provided for service \'%s\'',
245
                Connection::class,
246
                \stdClass::class,
247
                $serviceName
248
            )
249
        );
250
251
        $factory($this->container, $serviceName);
252
    }
253
254
    /**
255
     * Assert that a ServiceNotCreatedException is thrown from __invoke if the provided 'configuration'
256
     * string is not a valid configuration
257
     *
258
     * @throws ServiceNotFoundException
259
     * @throws ContainerExceptionInterface
260
     */
261
    public function testInvokeWillThrowServiceNotCreatedExceptionIfTheStringConfigurationCannotBeFound(): void
262
    {
263
        $factory = new EntityManagerFactory();
264
265
        $configurationName = 'BarConfigurationName';
266
        $serviceName = 'doctrine.entitymanager.orm_default';
267
        $emConfig = [
268
            'configuration' => $configurationName,
269
            'connection'    => 'FooConnectionName',
270
        ];
271
272
        $this->container->expects($this->once())
273
            ->method('has')
274
            ->with(ConfigurationManagerInterface::class)
275
            ->willReturn(true);
276
277
        $this->container->expects($this->exactly(2))
278
            ->method('get')
279
            ->withConsecutive(
280
                [EntityManagerConfigs::class],
281
                [ConfigurationManagerInterface::class]
282
            )->willReturnOnConsecutiveCalls(
283
                $this->entityManagerConfigs,
284
                $this->configurationManager
285
            );
286
287
        $this->entityManagerConfigs->expects($this->once())
288
            ->method('getEntityManagerConfig')
289
            ->with($serviceName)
290
            ->willReturn($emConfig);
291
292
        // Return false for container has() call will raise our exception for missing configuration
293
        $this->configurationManager->expects($this->once())
294
            ->method('hasConfiguration')
295
            ->with($configurationName)
296
            ->willReturn(false);
297
298
        $this->expectException(ServiceNotCreatedException::class);
299
        $this->expectExceptionMessage(
300
            sprintf(
301
                'Failed to load configuration \'%s\' for service \'%s\': '
302
                . 'The configuration has not been registered with the configuration manager',
303
                $configurationName,
304
                $serviceName
305
            )
306
        );
307
308
        $factory($this->container, $serviceName);
309
    }
310
311
    /**
312
     * Assert that a ServiceNotCreatedException is thrown from __invoke if the provided 'configuration'
313
     * string is unable to be created
314
     *
315
     * @throws ServiceNotFoundException
316
     * @throws ContainerExceptionInterface
317
     */
318
    public function testInvokeWillThrowServiceNotCreatedExceptionIfTheStringConfigurationCannotBeCreated(): void
319
    {
320
        $factory = new EntityManagerFactory();
321
322
        $configurationName = 'BarConfigurationName';
323
        $serviceName = 'doctrine.entitymanager.orm_default';
324
        $emConfig = [
325
            'configuration' => $configurationName,
326
            'connection'    => 'FooConnectionName',
327
        ];
328
329
        $this->container->expects($this->once())
330
            ->method('has')
331
            ->with(ConfigurationManagerInterface::class)
332
            ->willReturn(true);
333
334
        $this->container->expects($this->exactly(2))
335
            ->method('get')
336
            ->withConsecutive(
337
                [EntityManagerConfigs::class],
338
                [ConfigurationManagerInterface::class]
339
            )->willReturnOnConsecutiveCalls(
340
                $this->entityManagerConfigs,
341
                $this->configurationManager
342
            );
343
344
        $this->entityManagerConfigs->expects($this->once())
345
            ->method('getEntityManagerConfig')
346
            ->with($serviceName)
347
            ->willReturn($emConfig);
348
349
        $this->configurationManager->expects($this->once())
350
            ->method('hasConfiguration')
351
            ->with($configurationName)
352
            ->willReturn(true);
353
354
        $exceptionMessage = 'This is a test exception message for ' . __METHOD__;
355
        $exceptionCode = 123;
356
        $exception = new ConfigurationManagerException($exceptionMessage, $exceptionCode);
357
358
        $this->configurationManager->expects($this->once())
359
            ->method('getConfiguration')
360
            ->with($configurationName)
361
            ->willThrowException($exception);
362
363
        $this->expectException(ServiceNotCreatedException::class);
364
        $this->expectExceptionCode($exceptionCode);
365
        $this->expectExceptionMessage(
366
            sprintf(
367
                'Failed to load configuration \'%s\' for service \'%s\': %s',
368
                $configurationName,
369
                $serviceName,
370
                $exceptionMessage
371
            )
372
        );
373
374
        $factory($this->container, $serviceName);
375
    }
376
377
    /**
378
     * Assert that a ServiceNotCreatedException is thrown from __invoke if the provided 'connection'
379
     * string is not a valid connection
380
     *
381
     * @throws ServiceNotFoundException
382
     * @throws ContainerExceptionInterface
383
     */
384
    public function testInvokeWillThrowServiceNotCreatedExceptionIfTheStringConnectionCannotBeFound(): void
385
    {
386
        $factory = new EntityManagerFactory();
387
388
        /** @var Configuration|MockObject $configuration */
389
        $configuration = $this->createMock(Configuration::class);
390
        $connectionName = 'FooConnectionName';
391
        $serviceName = 'doctrine.entitymanager.orm_default';
392
        $emConfig = [
393
            'configuration' => $configuration,
394
            'connection'    => $connectionName,
395
        ];
396
397
        $this->container->expects($this->exactly(2))
398
            ->method('has')
399
            ->withConsecutive([ConfigurationManagerInterface::class], [ConnectionManagerInterface::class])
400
            ->willReturnOnConsecutiveCalls(true, true);
401
402
        $this->container->expects($this->exactly(3))
403
            ->method('get')
404
            ->withConsecutive(
405
                [EntityManagerConfigs::class],
406
                [ConfigurationManagerInterface::class],
407
                [ConnectionManagerInterface::class]
408
            )->willReturnOnConsecutiveCalls(
409
                $this->entityManagerConfigs,
410
                $this->configurationManager,
411
                $this->connectionManager
412
            );
413
414
        $this->entityManagerConfigs->expects($this->once())
415
            ->method('getEntityManagerConfig')
416
            ->with($serviceName)
417
            ->willReturn($emConfig);
418
419
        // Return false for container has() call will raise our exception for missing configuration
420
        $this->connectionManager->expects($this->once())
421
            ->method('hasConnection')
422
            ->with($connectionName)
423
            ->willReturn(false);
424
425
        $this->expectException(ServiceNotCreatedException::class);
426
        $this->expectExceptionMessage(
427
            sprintf(
428
                'Failed to load connection \'%s\' for service \'%s\': '
429
                . 'The connection has not been registered with the connection manager',
430
                $connectionName,
431
                $serviceName
432
            )
433
        );
434
435
        $factory($this->container, $serviceName);
436
    }
437
438
    /**
439
     * Assert that a ServiceNotCreatedException is thrown from __invoke if the provided 'connection'
440
     * string is unable to be created
441
     *
442
     * @throws ServiceNotFoundException
443
     * @throws ContainerExceptionInterface
444
     */
445
    public function testInvokeWillThrowServiceNotCreatedExceptionIfTheStringConnectionCannotBeCreated(): void
446
    {
447
        $factory = new EntityManagerFactory();
448
449
        /** @var Configuration|MockObject $configuration */
450
        $configuration = $this->createMock(Configuration::class);
451
        $connectionName = 'FooConnectionName';
452
        $serviceName = 'doctrine.entitymanager.orm_default';
453
        $emConfig = [
454
            'configuration' => $configuration,
455
            'connection'    => $connectionName,
456
        ];
457
458
        $this->container->expects($this->exactly(2))
459
            ->method('has')
460
            ->withConsecutive([ConfigurationManagerInterface::class], [ConnectionManagerInterface::class])
461
            ->willReturnOnConsecutiveCalls(true, true);
462
463
        $this->container->expects($this->exactly(3))
464
            ->method('get')
465
            ->withConsecutive(
466
                [EntityManagerConfigs::class],
467
                [ConfigurationManagerInterface::class],
468
                [ConnectionManagerInterface::class]
469
            )->willReturnOnConsecutiveCalls(
470
                $this->entityManagerConfigs,
471
                $this->configurationManager,
472
                $this->connectionManager
473
            );
474
475
        $this->entityManagerConfigs->expects($this->once())
476
            ->method('getEntityManagerConfig')
477
            ->with($serviceName)
478
            ->willReturn($emConfig);
479
480
        $this->connectionManager->expects($this->once())
481
            ->method('hasConnection')
482
            ->with($connectionName)
483
            ->willReturn(true);
484
485
        $exceptionMessage = 'This is a test exception message for ' . __METHOD__;
486
        $exceptionCode = 123;
487
        $exception = new ConnectionManagerException($exceptionMessage, $exceptionCode);
488
489
        $this->connectionManager->expects($this->once())
490
            ->method('getConnection')
491
            ->with($connectionName)
492
            ->willThrowException($exception);
493
494
        $this->expectException(ServiceNotCreatedException::class);
495
        $this->expectExceptionCode($exceptionCode);
496
        $this->expectExceptionMessage(
497
            sprintf(
498
                'Failed to load connection \'%s\' for service \'%s\': %s',
499
                $connectionName,
500
                $serviceName,
501
                $exceptionMessage
502
            )
503
        );
504
505
        $factory($this->container, $serviceName);
506
    }
507
}
508