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

testImplementsEntityManagerProviderInterface()   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\Service\EntityManager;
6
7
use Arp\LaminasDoctrine\Config\DoctrineConfig;
8
use Arp\LaminasDoctrine\Factory\Service\EntityManagerFactory;
9
use Arp\LaminasDoctrine\Service\EntityManager\ContainerInterface;
10
use Arp\LaminasDoctrine\Service\EntityManager\EntityManagerProvider;
11
use Arp\LaminasDoctrine\Service\EntityManager\EntityManagerProviderInterface;
12
use Arp\LaminasDoctrine\Service\EntityManager\Exception\EntityManagerProviderException;
13
use Doctrine\ORM\EntityManagerInterface;
14
use Laminas\ServiceManager\Exception\ServiceNotCreatedException;
15
use PHPUnit\Framework\MockObject\MockObject;
16
use PHPUnit\Framework\TestCase;
17
18
/**
19
 * @covers  \Arp\LaminasDoctrine\Service\EntityManager\EntityManagerProvider
20
 *
21
 * @author  Alex Patterson <[email protected]>
22
 * @package ArpTest\LaminasDoctrine\Service\EntityManager
23
 */
24
final class EntityManagerProviderTest extends TestCase
25
{
26
    /**
27
     * @var DoctrineConfig|MockObject
28
     */
29
    private $config;
30
31
    /**
32
     * @var ContainerInterface|MockObject
33
     */
34
    private $container;
35
36
    /**
37
     * Prepare the test case dependencies
38
     */
39
    public function setUp(): void
40
    {
41
        $this->config = $this->createMock(DoctrineConfig::class);
42
43
        $this->container = $this->createMock(ContainerInterface::class);
44
    }
45
46
    /**
47
     * Assert the class is an instance of the EntityManagerProviderInterface
48
     */
49
    public function testImplementsEntityManagerProviderInterface(): void
50
    {
51
        $provider = new EntityManagerProvider($this->config, $this->container);
52
53
        $this->assertInstanceOf(EntityManagerProviderInterface::class, $provider);
54
    }
55
56
    /**
57
     * Assert has() will return the expected boolean result
58
     *
59
     * @param bool $expected
60
     * @param bool $hasContainer
61
     * @param bool $hasConfig
62
     *
63
     * @dataProvider getHasData
64
     */
65
    public function testHas(bool $expected, bool $hasContainer, bool $hasConfig): void
66
    {
67
        $name = 'FooServiceName';
68
        if ($hasContainer) {
69
            $this->container->expects($this->once())
70
                ->method('has')
71
                ->with($name)
72
                ->willReturn($hasContainer);
73
        }
74
75
        if (!$hasContainer) {
76
            $this->config->expects($this->once())
77
                ->method('hasEntityManagerConfig')
78
                ->with($name)
79
                ->willReturn($hasConfig);
80
        }
81
82
        $provider = new EntityManagerProvider($this->config, $this->container);
83
84
        $this->assertSame($expected, $provider->hasEntityManager($name));
85
    }
86
87
    /**
88
     * @return array
89
     */
90
    public function getHasData(): array
91
    {
92
        return [
93
            [true, true, true],
94
            [true, true, false],
95
            [true, false, true],
96
            [false, false, false],
97
        ];
98
    }
99
100
    /**
101
     * Assert that getCollection() will return a matching connection by name
102
     *
103
     * @throws EntityManagerProviderException
104
     */
105
    public function testGetEntityManagerWillReturnEntityManagerByName(): void
106
    {
107
        $provider = new EntityManagerProvider($this->config, $this->container);
108
109
        /** @var EntityManagerInterface|MockObject $entityManager */
110
        $entityManager = $this->createMock(EntityManagerInterface::class);
111
        $name = 'FooEntityManager';
112
113
        $this->container->expects($this->exactly(2))
114
            ->method('has')
115
            ->withConsecutive([$name], [$name])
116
            ->willReturn(true, true);
117
118
        $this->container->expects($this->once())
119
            ->method('get')
120
            ->with($name)
121
            ->willReturn($entityManager);
122
123
        $this->assertSame($entityManager, $provider->getEntityManager($name));
124
    }
125
126
    /**
127
     * Assert that a single entity manager can be set and then returned by its $name
128
     *
129
     * @throws EntityManagerProviderException
130
     */
131
    public function testSetAndGetEntityManager(): void
132
    {
133
        $provider = new EntityManagerProvider($this->config, $this->container);
134
135
        /** @var EntityManagerInterface|MockObject $entityManager */
136
        $entityManager = $this->createMock(EntityManagerInterface::class);
137
        $name = 'FooEntityManager';
138
139
        $this->container->expects($this->once())
140
            ->method('setService')
141
            ->with($name, $entityManager);
142
143
        $provider->setEntityManager($name, $entityManager);
144
145
        $this->container->expects($this->exactly(2))
146
            ->method('has')
147
            ->withConsecutive([$name], [$name])
148
            ->willReturnOnConsecutiveCalls(true, true);
149
150
        $this->container->expects($this->once())
151
            ->method('get')
152
            ->with($name)
153
            ->willReturn($entityManager);
154
155
        $this->assertSame($entityManager, $provider->getEntityManager($name));
156
    }
157
158
    /**
159
     * Assert that a multiple entity manager can be set and then returned by their names
160
     */
161
    public function testSetAndGetEntityManagers(): void
162
    {
163
        /** @var EntityManagerInterface[]|MockObject[]|array[] $configs */
164
        $configs = [
165
            'foo' => $this->createMock(EntityManagerInterface::class),
166
            'bar' => $this->createMock(EntityManagerInterface::class),
167
            'test' => [
168
                'name' => 'hello',
169
                'test' => 'data',
170
                'active' => true,
171
            ],
172
        ];
173
174
        $provider = new EntityManagerProvider($this->config, $this->container);
175
176
        $setArgs = $configsArgs = [];
177
        foreach ($configs as $name => $config) {
178
            if (is_array($config)) {
179
                $configsArgs[] = [$name, $config];
180
            } else {
181
                $setArgs[] = [$name, $config];
182
            }
183
        }
184
185
        $this->container->expects($this->exactly(count($setArgs)))
186
            ->method('setService')
187
            ->withConsecutive(...$setArgs);
188
189
        $this->config->expects($this->exactly(count($configsArgs)))
190
            ->method('setEntityManagerConfig')
191
            ->withConsecutive(...$configsArgs);
192
193
        $provider->setEntityManagers($configs);
194
    }
195
196
    /**
197
     * Assert that getCollection() will return a connection by lazy loading the configuration
198
     *
199
     * @throws EntityManagerProviderException
200
     */
201
    public function testGetEntityManagerWillReturnLazyLoadedEntityManagerByName(): void
202
    {
203
        $provider = new EntityManagerProvider($this->config, $this->container);
204
205
        /** @var EntityManagerInterface|MockObject $entityManager */
206
        $entityManager = $this->createMock(EntityManagerInterface::class);
207
        $name = 'FooEntityManager';
208
        $config = [
209
            'foo' => 'bar',
210
        ];
211
212
        $this->container->expects($this->exactly(3))
213
            ->method('has')
214
            ->withConsecutive([$name], [$name], [$name])
215
            ->willReturn(false, false, true);
216
217
        $this->config->expects($this->once())
218
            ->method('hasEntityManagerConfig')
219
            ->with($name)
220
            ->willReturn(true);
221
222
        $this->config->expects($this->once())
223
            ->method('getEntityManagerConfig')
224
            ->with($name)
225
            ->willReturn($config);
226
227
        $this->container->expects($this->once())
228
            ->method('setFactory')
229
            ->with($name, EntityManagerFactory::class);
230
231
        $this->container->expects($this->once())
232
            ->method('build')
233
            ->with($name, $config)
234
            ->willReturn($entityManager);
235
236
        $this->container->expects($this->once())
237
            ->method('get')
238
            ->with($name)
239
            ->willReturn($entityManager);
240
241
        $this->assertSame($entityManager, $provider->getEntityManager($name));
242
    }
243
244
    /**
245
     * Assert a EntityManagerProviderException is thrown from getEntityManager() if the provided $name can not be
246
     * resolved to a valid entity manager instance
247
     *
248
     * @throws EntityManagerProviderException
249
     */
250
    public function testGetEntityManagerWillThrowEntityManagerProviderExceptionIfNotFound(): void
251
    {
252
        $provider = new EntityManagerProvider($this->config, $this->container);
253
254
        $name = 'EntityManagerTest';
255
256
        $this->container->expects($this->exactly(2))
257
            ->method('has')
258
            ->withConsecutive([$name], [$name])
259
            ->willReturnOnConsecutiveCalls(false, false);
260
261
        $this->config->expects($this->once())
262
            ->method('hasEntityManagerConfig')
263
            ->with($name)
264
            ->willReturn(false);
265
266
        $this->expectException(EntityManagerProviderException::class);
267
        $this->expectExceptionMessage(sprintf('Unable to find entity manager \'%s\'', $name));
268
269
        $provider->refresh($name);
270
    }
271
272
    /**
273
     * Assert a EntityManagerProviderException is thrown from getEntityManager() if the lazy loaded entity manager
274
     * cannot be created
275
     *
276
     * @throws EntityManagerProviderException
277
     */
278
    public function testGetEntityManagerWillThrowEntityManagerProviderExceptionIfNotCreated(): void
279
    {
280
        $provider = new EntityManagerProvider($this->config, $this->container);
281
282
        $name = 'EntityManagerTest';
283
        $config = [
284
            'foo' => 123,
285
            'bar' => 'Hello World!',
286
        ];
287
288
        $this->container->expects($this->exactly(2))
289
            ->method('has')
290
            ->withConsecutive([$name], [$name])
291
            ->willReturnOnConsecutiveCalls(false, false);
292
293
        $this->config->expects($this->once())
294
            ->method('hasEntityManagerConfig')
295
            ->with($name)
296
            ->willReturn(true);
297
298
        $this->config->expects($this->once())
299
            ->method('getEntityManagerConfig')
300
            ->with($name)
301
            ->willReturn($config);
302
303
        $this->container->expects($this->once())
304
            ->method('setFactory')
305
            ->with($name, EntityManagerFactory::class);
306
307
        $exceptionMessage = 'This is a test exception message for ' . __FUNCTION__;
308
        $exceptionCode = 12345;
309
        $exception = new ServiceNotCreatedException($exceptionMessage, $exceptionCode);
310
311
        $this->container->expects($this->once())
312
            ->method('build')
313
            ->with($name, $config)
314
            ->willThrowException($exception);
315
316
        $this->expectException(EntityManagerProviderException::class);
317
        $this->expectExceptionCode($exceptionCode);
318
        $this->expectExceptionMessage(
319
            sprintf('Failed to create entity manager \'%s\' from configuration: %s', $name, $exceptionMessage)
320
        );
321
322
        $provider->getEntityManager($name);
323
    }
324
325
    /**
326
     * Assert a EntityManagerProviderException is thrown from getEntityManager() if the lazy loaded entity manager
327
     * cannot be returned from the container
328
     *
329
     * @throws EntityManagerProviderException
330
     */
331
    public function testGetEntityManagerWillThrowEntityManagerProviderExceptionIfNotRetrieved(): void
332
    {
333
        $provider = new EntityManagerProvider($this->config, $this->container);
334
335
        $name = 'EntityManagerTest';
336
337
        $this->container->expects($this->exactly(2))
338
            ->method('has')
339
            ->withConsecutive([$name], [$name])
340
            ->willReturnOnConsecutiveCalls(true, true);
341
342
        $exceptionMessage = 'This is a test exception message for ' . __FUNCTION__;
343
        $exceptionCode = 54321;
344
        $exception = new ServiceNotCreatedException($exceptionMessage, $exceptionCode);
345
346
        $this->container->expects($this->once())
347
            ->method('get')
348
            ->with($name)
349
            ->willThrowException($exception);
350
351
        $this->expectException(EntityManagerProviderException::class);
352
        $this->expectExceptionCode($exceptionCode);
353
        $this->expectExceptionMessage(
354
            sprintf('Failed retrieve entity manager \'%s\': %s', $name, $exceptionMessage),
355
        );
356
357
        $provider->getEntityManager($name);
358
    }
359
360
    /**
361
     * Assert an EntityManager instance can be refreshed by closing the existing connection and creating a new
362
     * instance based on the configuration
363
     *
364
     * @throws EntityManagerProviderException
365
     */
366
    public function testRefresh(): void
367
    {
368
        $provider = new EntityManagerProvider($this->config, $this->container);
369
370
        $name = 'FooEntityManager';
371
372
        /** @var EntityManagerInterface|MockObject $entityManager */
373
        $entityManager = $this->createMock(EntityManagerInterface::class);
374
375
        /** @var EntityManagerInterface|MockObject $newInstance */
376
        $newInstance = $this->createMock(EntityManagerInterface::class);
377
378
        $config = [
379
            'foo' => 123,
380
            'bar' => 'test',
381
        ];
382
383
        $this->container->expects($this->exactly(4))
384
            ->method('has')
385
            ->withConsecutive([$name], [$name], [$name], [$name])
386
            ->willReturnOnConsecutiveCalls(true, true, true, true);
387
388
        $this->container->expects($this->once())
389
            ->method('get')
390
            ->with($name)
391
            ->willReturn($entityManager);
392
393
        $entityManager->expects($this->once())
394
            ->method('isOpen')
395
            ->willReturn(true);
396
397
        $entityManager->expects($this->once())
398
            ->method('close');
399
400
        $this->config->expects($this->once())
401
            ->method('getEntityManagerConfig')
402
            ->with($name)
403
            ->willReturn($config);
404
405
        $this->container->expects($this->once())
406
            ->method('build')
407
            ->with($name, $config)
408
            ->willReturn($newInstance);
409
410
        $this->assertSame($newInstance, $provider->refresh($name));
411
    }
412
}
413