Test Failed
Pull Request — master (#2)
by Alex
04:49 queued 01:37
created

EntityManagerFactoryTest::testIsInvokable()   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
eloc 2
c 1
b 0
f 0
dl 0
loc 5
rs 10
cc 1
nc 1
nop 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace ArpTest\LaminasDoctrine\Factory\Service;
6
7
use Arp\LaminasDoctrine\Config\DoctrineConfig;
8
use Arp\LaminasDoctrine\Factory\Service\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 PHPUnit\Framework\MockObject\MockObject;
17
use PHPUnit\Framework\TestCase;
18
use Psr\Container\ContainerInterface;
19
20
/**
21
 * @covers \Arp\LaminasDoctrine\Factory\Service\EntityManagerFactory
22
 *
23
 * @author  Alex Patterson <[email protected]>
24
 * @package ArpTest\LaminasDoctrine\Factory\Service
25
 */
26
final class EntityManagerFactoryTest extends TestCase
27
{
28
    /**
29
     * @var ContainerInterface|MockObject
30
     */
31
    private $container;
32
33
    /**
34
     * @var DoctrineConfig
35
     */
36
    private $doctrineConfig;
37
38
    /**
39
     * @var ConfigurationManagerInterface|MockObject
40
     */
41
    private $configurationManager;
42
43
    /**
44
     * @var ConnectionManagerInterface|MockObject
45
     */
46
    private $connectionManager;
47
48
    /**
49
     * Prepare the test case dependencies
50
     */
51
    public function setUp(): void
52
    {
53
        $this->container = $this->createMock(ContainerInterface::class);
54
55
        $this->doctrineConfig = $this->createMock(DoctrineConfig::class);
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->createMock(Arp\La...\DoctrineConfig::class) of type PHPUnit\Framework\MockObject\MockObject is incompatible with the declared type Arp\LaminasDoctrine\Config\DoctrineConfig of property $doctrineConfig.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
56
57
        $this->configurationManager = $this->createMock(ConfigurationManagerInterface::class);
58
59
        $this->connectionManager = $this->createMock(ConnectionManagerInterface::class);
60
    }
61
62
    /**
63
     * Assert that factory is a callable instance
64
     */
65
    public function testIsInvokable(): void
66
    {
67
        $factory = new EntityManagerFactory();
68
69
        $this->assertIsCallable($factory);
70
    }
71
72
    /**
73
     * Assert a ServiceNotCreateException is thrown from __invoke() if the required 'configuration' configuration
74
     * option is missing or null
75
     */
76
    public function testInvokeWillThrowServiceNotCreatedExceptionIfTheRequiredConfigurationConfigIsMissing(): void
77
    {
78
        /** @var EntityManagerFactory|MockObject $factory */
79
        $factory = new EntityManagerFactory();
80
81
        $serviceName = 'doctrine.entitymanager.orm_default';
82
        $emConfig = [
83
            'connection' => 'FooConnectionName',
84
            // missing 'configuration' key
85
        ];
86
87
        $this->container->expects($this->once())
88
            ->method('has')
89
            ->with(DoctrineConfig::class)
90
            ->willReturn(true);
91
92
        $this->container->expects($this->once())
93
            ->method('get')
94
            ->with(DoctrineConfig::class)
95
            ->willReturn($this->doctrineConfig);
96
97
        $this->doctrineConfig->expects($this->once())
0 ignored issues
show
Bug introduced by
The method expects() does not exist on Arp\LaminasDoctrine\Config\DoctrineConfig. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

97
        $this->doctrineConfig->/** @scrutinizer ignore-call */ 
98
                               expects($this->once())

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
98
            ->method('getEntityManagerConfig')
99
            ->with($serviceName)
100
            ->willReturn($emConfig);
101
102
        $this->expectException(ServiceNotCreatedException::class);
103
        $this->expectExceptionMessage(
104
            sprintf(
105
                'The required \'configuration\' configuration option is missing for service \'%s\'',
106
                $serviceName
107
            )
108
        );
109
110
        $factory($this->container, $serviceName);
111
    }
112
113
    /**
114
     * Assert a ServiceNotCreateException is thrown from __invoke() if the required 'connection' configuration
115
     * option is missing or null
116
     */
117
    public function testInvokeWillThrowServiceNotCreatedExceptionIfTheRequiredConnectionConfigIsMissing(): void
118
    {
119
        /** @var EntityManagerFactory|MockObject $factory */
120
        $factory = new EntityManagerFactory();
121
122
        $serviceName = 'doctrine.entitymanager.orm_default';
123
        $emConfig = [
124
            'connection' => null,
125
            'configuration' => 'BarConfigurationName',
126
        ];
127
128
        $this->container->expects($this->once())
129
            ->method('has')
130
            ->with(DoctrineConfig::class)
131
            ->willReturn(true);
132
133
        $this->container->expects($this->once())
134
            ->method('get')
135
            ->with(DoctrineConfig::class)
136
            ->willReturn($this->doctrineConfig);
137
138
        $this->doctrineConfig->expects($this->once())
139
            ->method('getEntityManagerConfig')
140
            ->with($serviceName)
141
            ->willReturn($emConfig);
142
143
        $this->expectException(ServiceNotCreatedException::class);
144
        $this->expectExceptionMessage(
145
            sprintf(
146
                'The required \'connection\' configuration option is missing for service \'%s\'',
147
                $serviceName
148
            )
149
        );
150
151
        $factory($this->container, $serviceName);
152
    }
153
154
    /**
155
     * Assert a ServiceNotCreateException is thrown from __invoke() if the required 'configuration' object
156
     * is of an invalid type
157
     */
158
    public function testInvokeWillThrowServiceNotCreatedExceptionIfTheRequiredConfigurationIsInvalid(): void
159
    {
160
        /** @var EntityManagerFactory|MockObject $factory */
161
        $factory = new EntityManagerFactory();
162
163
        $configuration = new \stdClass(); // invalid configuration class
164
        $serviceName = 'doctrine.entitymanager.orm_default';
165
        $emConfig = [
166
            'configuration' => $configuration,
167
            'connection' => 'BarConnectionName',
168
        ];
169
170
        $this->container->expects($this->exactly(2))
171
            ->method('has')
172
            ->withConsecutive([DoctrineConfig::class], [ConfigurationManagerInterface::class])
173
            ->willReturnOnConsecutiveCalls(true, true);
174
175
        $this->container->expects($this->exactly(2))
176
            ->method('get')
177
            ->withConsecutive([DoctrineConfig::class], [ConfigurationManagerInterface::class])
178
            ->willReturnOnConsecutiveCalls($this->doctrineConfig, $this->configurationManager);
179
180
        $this->doctrineConfig->expects($this->once())
181
            ->method('getEntityManagerConfig')
182
            ->with($serviceName)
183
            ->willReturn($emConfig);
184
185
        $this->expectException(ServiceNotCreatedException::class);
186
        $this->expectExceptionMessage(
187
            sprintf(
188
                'The configuration must be an object of type \'%s\'; \'%s\' provided for service \'%s\'',
189
                Configuration::class,
190
                \stdClass::class,
191
                $serviceName
192
            )
193
        );
194
195
        $factory($this->container, $serviceName);
196
    }
197
198
    /**
199
     * Assert a ServiceNotCreateException is thrown from __invoke() if the required 'connection' object
200
     * is of an invalid type
201
     */
202
    public function testInvokeWillThrowServiceNotCreatedExceptionIfTheRequiredConnectionIsInvalid(): void
203
    {
204
        /** @var EntityManagerFactory|MockObject $factory */
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(3))
219
            ->method('has')
220
            ->withConsecutive(
221
                [DoctrineConfig::class],
222
                [ConfigurationManagerInterface::class],
223
                [ConnectionManagerInterface::class]
224
            )
225
            ->willReturnOnConsecutiveCalls(true, true, true);
226
227
        $this->container->expects($this->exactly(3))
228
            ->method('get')
229
            ->withConsecutive(
230
                [DoctrineConfig::class],
231
                [ConfigurationManagerInterface::class],
232
                [ConnectionManagerInterface::class]
233
            )
234
            ->willReturnOnConsecutiveCalls(
235
                $this->doctrineConfig,
236
                $this->configurationManager,
237
                $this->connectionManager
238
            );
239
240
        $this->doctrineConfig->expects($this->once())
241
            ->method('getEntityManagerConfig')
242
            ->with($serviceName)
243
            ->willReturn($emConfig);
244
245
        $this->expectException(ServiceNotCreatedException::class);
246
        $this->expectExceptionMessage(
247
            sprintf(
248
                'The connection must be an object of type \'%s\'; \'%s\' provided for service \'%s\'',
249
                Connection::class,
250
                \stdClass::class,
251
                $serviceName
252
            )
253
        );
254
255
        $factory($this->container, $serviceName);
256
    }
257
258
    /**
259
     * Assert that a ServiceNotCreatedException is thrown from __invoke if the provided 'configuration'
260
     * string is not a valid configuration
261
     */
262
    public function testInvokeWillThrowServiceNotCreatedExceptionIfTheStringConfigurationCannotBeFound(): void
263
    {
264
        /** @var EntityManagerFactory|MockObject $factory */
265
        $factory = new EntityManagerFactory();
266
267
        $configurationName = 'BarConfigurationName';
268
        $serviceName = 'doctrine.entitymanager.orm_default';
269
        $emConfig = [
270
            'configuration' => $configurationName,
271
            'connection' => 'FooConnectionName',
272
        ];
273
274
        $this->container->expects($this->exactly(2))
275
            ->method('has')
276
            ->withConsecutive(
277
                [DoctrineConfig::class],
278
                [ConfigurationManagerInterface::class]
279
            )
280
            ->willReturnOnConsecutiveCalls(true, true);
281
282
        $this->container->expects($this->exactly(2))
283
            ->method('get')
284
            ->withConsecutive(
285
                [DoctrineConfig::class],
286
                [ConfigurationManagerInterface::class]
287
            )->willReturnOnConsecutiveCalls(
288
                $this->doctrineConfig,
289
                $this->configurationManager
290
            );
291
292
        $this->doctrineConfig->expects($this->once())
293
            ->method('getEntityManagerConfig')
294
            ->with($serviceName)
295
            ->willReturn($emConfig);
296
297
        // Return false for container has() call will raise our exception for missing configuration
298
        $this->configurationManager->expects($this->once())
299
            ->method('hasConfiguration')
300
            ->with($configurationName)
301
            ->willReturn(false);
302
303
        $this->expectException(ServiceNotCreatedException::class);
304
        $this->expectExceptionMessage(
305
            sprintf(
306
                'Failed to load configuration \'%s\' for service \'%s\': '
307
                . 'The configuration has not been registered with the configuration manager',
308
                $configurationName,
309
                $serviceName
310
            )
311
        );
312
313
        $factory($this->container, $serviceName);
314
    }
315
316
    /**
317
     * Assert that a ServiceNotCreatedException is thrown from __invoke if the provided 'configuration'
318
     * string is unable to be created
319
     */
320
    public function testInvokeWillThrowServiceNotCreatedExceptionIfTheStringConfigurationCannotBeCreated(): void
321
    {
322
        /** @var EntityManagerFactory|MockObject $factory */
323
        $factory = new EntityManagerFactory();
324
325
        $configurationName = 'BarConfigurationName';
326
        $serviceName = 'doctrine.entitymanager.orm_default';
327
        $emConfig = [
328
            'configuration' => $configurationName,
329
            'connection' => 'FooConnectionName',
330
        ];
331
332
        $this->container->expects($this->exactly(2))
333
            ->method('has')
334
            ->withConsecutive(
335
                [DoctrineConfig::class],
336
                [ConfigurationManagerInterface::class]
337
            )
338
            ->willReturnOnConsecutiveCalls(true, true);
339
340
        $this->container->expects($this->exactly(2))
341
            ->method('get')
342
            ->withConsecutive(
343
                [DoctrineConfig::class],
344
                [ConfigurationManagerInterface::class]
345
            )->willReturnOnConsecutiveCalls(
346
                $this->doctrineConfig,
347
                $this->configurationManager
348
            );
349
350
        $this->doctrineConfig->expects($this->once())
351
            ->method('getEntityManagerConfig')
352
            ->with($serviceName)
353
            ->willReturn($emConfig);
354
355
        $this->configurationManager->expects($this->once())
356
            ->method('hasConfiguration')
357
            ->with($configurationName)
358
            ->willReturn(true);
359
360
        $exceptionMessage = 'This is a test exception message for ' . __METHOD__;
361
        $exceptionCode = 123;
362
        $exception = new ConfigurationManagerException($exceptionMessage, $exceptionCode);
363
364
        $this->configurationManager->expects($this->once())
365
            ->method('getConfiguration')
366
            ->with($configurationName)
367
            ->willThrowException($exception);
368
369
        $this->expectException(ServiceNotCreatedException::class);
370
        $this->expectExceptionCode($exceptionCode);
371
        $this->expectExceptionMessage(
372
            sprintf(
373
                'Failed to load configuration \'%s\' for service \'%s\': %s',
374
                $configurationName,
375
                $serviceName,
376
                $exceptionMessage
377
            )
378
        );
379
380
        $factory($this->container, $serviceName);
381
    }
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
    /**
398
     * Assert that a ServiceNotCreatedException is thrown from __invoke if the provided 'connection'
399
     * string is not a valid connection
400
     */
401
    public function testInvokeWillThrowServiceNotCreatedExceptionIfTheStringConnectionCannotBeFound(): void
402
    {
403
        /** @var EntityManagerFactory|MockObject $factory */
404
        $factory = new EntityManagerFactory();
405
406
        /** @var Configuration|MockObject $configuration */
407
        $configuration = $this->createMock(Configuration::class);
408
        $connectionName = 'FooConnectionName';
409
        $serviceName = 'doctrine.entitymanager.orm_default';
410
        $emConfig = [
411
            'configuration' => $configuration,
412
            'connection' => $connectionName,
413
        ];
414
415
        $this->container->expects($this->exactly(3))
416
            ->method('has')
417
            ->withConsecutive(
418
                [DoctrineConfig::class],
419
                [ConfigurationManagerInterface::class],
420
                [ConnectionManagerInterface::class]
421
            )
422
            ->willReturnOnConsecutiveCalls(true, true, true);
423
424
        $this->container->expects($this->exactly(3))
425
            ->method('get')
426
            ->withConsecutive(
427
                [DoctrineConfig::class],
428
                [ConfigurationManagerInterface::class],
429
                [ConnectionManagerInterface::class]
430
            )->willReturnOnConsecutiveCalls(
431
                $this->doctrineConfig,
432
                $this->configurationManager,
433
                $this->connectionManager
434
            );
435
436
        $this->doctrineConfig->expects($this->once())
437
            ->method('getEntityManagerConfig')
438
            ->with($serviceName)
439
            ->willReturn($emConfig);
440
441
        // Return false for container has() call will raise our exception for missing configuration
442
        $this->connectionManager->expects($this->once())
443
            ->method('hasConnection')
444
            ->with($connectionName)
445
            ->willReturn(false);
446
447
        $this->expectException(ServiceNotCreatedException::class);
448
        $this->expectExceptionMessage(
449
            sprintf(
450
                'Failed to load connection \'%s\' for service \'%s\': '
451
                . 'The connection has not been registered with the connection manager',
452
                $connectionName,
453
                $serviceName
454
            )
455
        );
456
457
        $factory($this->container, $serviceName);
458
    }
459
460
    /**
461
     * Assert that a ServiceNotCreatedException is thrown from __invoke if the provided 'connection'
462
     * string is unable to be created
463
     */
464
    public function testInvokeWillThrowServiceNotCreatedExceptionIfTheStringConnectionCannotBeCreated(): void
465
    {
466
        /** @var EntityManagerFactory|MockObject $factory */
467
        $factory = new EntityManagerFactory();
468
469
        /** @var Configuration|MockObject $configuration */
470
        $configuration = $this->createMock(Configuration::class);
471
        $connectionName = 'FooConnectionName';
472
        $serviceName = 'doctrine.entitymanager.orm_default';
473
        $emConfig = [
474
            'configuration' => $configuration,
475
            'connection' => $connectionName,
476
        ];
477
478
        $this->container->expects($this->exactly(3))
479
            ->method('has')
480
            ->withConsecutive(
481
                [DoctrineConfig::class],
482
                [ConfigurationManagerInterface::class],
483
                [ConnectionManagerInterface::class]
484
            )
485
            ->willReturnOnConsecutiveCalls(true, true, true);
486
487
        $this->container->expects($this->exactly(3))
488
            ->method('get')
489
            ->withConsecutive(
490
                [DoctrineConfig::class],
491
                [ConfigurationManagerInterface::class],
492
                [ConnectionManagerInterface::class]
493
            )->willReturnOnConsecutiveCalls(
494
                $this->doctrineConfig,
495
                $this->configurationManager,
496
                $this->connectionManager
497
            );
498
499
        $this->doctrineConfig->expects($this->once())
500
            ->method('getEntityManagerConfig')
501
            ->with($serviceName)
502
            ->willReturn($emConfig);
503
504
        $this->connectionManager->expects($this->once())
505
            ->method('hasConnection')
506
            ->with($connectionName)
507
            ->willReturn(true);
508
509
        $exceptionMessage = 'This is a test exception message for ' . __METHOD__;
510
        $exceptionCode = 123;
511
        $exception = new ConnectionManagerException($exceptionMessage, $exceptionCode);
512
513
        $this->connectionManager->expects($this->once())
514
            ->method('getConnection')
515
            ->with($connectionName)
516
            ->willThrowException($exception);
517
518
        $this->expectException(ServiceNotCreatedException::class);
519
        $this->expectExceptionCode($exceptionCode);
520
        $this->expectExceptionMessage(
521
            sprintf(
522
                'Failed to load connection \'%s\' for service \'%s\': %s',
523
                $connectionName,
524
                $serviceName,
525
                $exceptionMessage
526
            )
527
        );
528
529
        $factory($this->container, $serviceName);
530
    }
531
}
532