Passed
Pull Request — master (#3)
by Alex
02:09
created

ContainerTest::testImplementsContainerInterface()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 2
c 0
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\Container;
6
7
use Arp\Container\Adapter\ContainerAdapterInterface;
8
use Arp\Container\Adapter\Exception\AdapterException;
9
use Arp\Container\Adapter\Exception\NotFoundException as AdapterNotFoundException;
10
use Arp\Container\Container;
11
use Arp\Container\Exception\ContainerException;
12
use Arp\Container\Exception\NotFoundException;
13
use Arp\Container\Provider\Exception\ServiceProviderException;
14
use Arp\Container\Provider\ServiceProviderInterface;
15
use PHPUnit\Framework\MockObject\MockObject;
16
use PHPUnit\Framework\TestCase;
17
use Psr\Container\ContainerExceptionInterface;
18
use Psr\Container\ContainerInterface;
19
20
/**
21
 * @covers  \Arp\Container\Container
22
 *
23
 * @author  Alex Patterson <[email protected]>
24
 * @package ArpTest\Container
25
 */
26
final class ContainerTest extends TestCase
27
{
28
    /**
29
     * @var ContainerAdapterInterface|MockObject
30
     */
31
    private $adapter;
32
33
    /**
34
     * @return void
35
     */
36
    public function setUp(): void
37
    {
38
        $this->adapter = $this->getMockForAbstractClass(ContainerAdapterInterface::class);
39
    }
40
41
    /**
42
     * Ensure that the container implements the PSR
43
     */
44
    public function testImplementsContainerInterface(): void
45
    {
46
        $container = new Container($this->adapter);
47
48
        $this->assertInstanceOf(ContainerInterface::class, $container);
49
    }
50
51
    /**
52
     * Assert AdapterException thrown by has() will be caught and rethrown as ContainerException.
53
     *
54
     * @throws ContainerException
55
     */
56
    public function testHasWillCatchAdapterExceptionAndReThrowAsAContainerException(): void
57
    {
58
        $name = 'FooService';
59
60
        $container = new Container($this->adapter);
61
62
        $exceptionMessage = 'This is a test adapter exception message';
63
        $exception = new AdapterException($exceptionMessage);
64
65
        $this->adapter->expects($this->once())
66
            ->method('hasService')
67
            ->willThrowException($exception);
68
69
        $this->expectException(ContainerException::class);
70
        $this->expectExceptionMessage($exceptionMessage);
71
        $this->expectExceptionCode($exception->getCode());
72
73
        $container->has($name);
74
    }
75
76
    /**
77
     * Ensure that registered services will return true when calling has().
78
     *
79
     * @throws ContainerException
80
     */
81
    public function testHasReturnsTrueForRegisteredService(): void
82
    {
83
        $container = new Container($this->adapter);
84
85
        $serviceName = 'TestService';
86
87
        $this->adapter->expects($this->once())
88
            ->method('hasService')
89
            ->with($serviceName)
90
            ->willReturn(true);
91
92
        $this->assertTrue($container->has($serviceName));
93
    }
94
95
    /**
96
     * Ensure that non-registered services will return false when calling has().
97
     *
98
     * @throws ContainerException
99
     */
100
    public function testHasReturnsFalseForNonRegisteredService(): void
101
    {
102
        $container = new Container($this->adapter);
103
104
        $serviceName = 'TestService';
105
106
        $this->adapter->expects($this->once())
107
            ->method('hasService')
108
            ->with($serviceName)
109
            ->willReturn(false);
110
111
        $this->assertFalse($container->has($serviceName));
112
    }
113
114
    /**
115
     * Assert that if the requested service to get() fails to be found a NotFoundException is thrown.
116
     */
117
    public function testGetWillThrowNotFoundExceptionIfRequestedServiceIsNotFound(): void
118
    {
119
        $container = new Container($this->adapter);
120
121
        $name = 'FooService';
122
123
        $exceptionMessage = 'This is a test exception message';
124
        $exceptionCode = 999;
125
        $exception = new AdapterNotFoundException($exceptionMessage, $exceptionCode);
126
127
        $this->adapter->expects($this->once())
128
            ->method('getService')
129
            ->with($name)
130
            ->willThrowException($exception);
131
132
        $this->expectException(NotFoundException::class);
133
        $this->expectExceptionMessage($exceptionMessage);
134
        $this->expectExceptionCode($exceptionCode);
135
136
        $container->get($name);
137
    }
138
139
    /**
140
     * Assert that NotFoundException's thrown by the adapter are caught, logged and rethrown as
141
     * container NotFoundException's.
142
     */
143
    public function testGetWillThrowContainerExceptionIfGetServiceFails(): void
144
    {
145
        $container = new Container($this->adapter);
146
147
        $name = 'FooService';
148
149
        $exceptionMessage = 'This is a test exception message';
150
        $exceptionCode = 888;
151
        $exception = new AdapterException($exceptionMessage, $exceptionCode);
152
153
        $this->adapter->expects($this->once())
154
            ->method('getService')
155
            ->with($name)
156
            ->willThrowException($exception);
157
158
        $this->expectException(ContainerException::class);
159
        $this->expectExceptionMessage($exceptionMessage);
160
        $this->expectExceptionCode($exceptionCode);
161
162
        $container->get($name);
163
    }
164
165
    /**
166
     * Ensure that calls to get() will return a registered service from the adapter.
167
     *
168
     * @throws ContainerExceptionInterface
169
     */
170
    public function testGetWillReturnRegisteredService(): void
171
    {
172
        $container = new Container($this->adapter);
173
174
        $serviceName = 'TestService';
175
        $service = new \stdClass();
176
177
        $this->adapter->expects($this->once())
178
            ->method('getService')
179
            ->with($serviceName)
180
            ->willReturn($service);
181
182
        $this->assertSame($service, $container->get($serviceName));
183
    }
184
185
    /**
186
     * Assert that AdapterException's that are thrown when registering services are caught, logged and rethrow
187
     * as ContainerException.
188
     *
189
     * @throws ContainerException
190
     */
191
    public function testRegisterServiceWillCatchAndRethrowServiceProviderExceptionsAsContainerException(): void
192
    {
193
        $container = new Container($this->adapter);
194
195
        /** @var ServiceProviderInterface|MockObject $serviceProvider */
196
        $serviceProvider = $this->getMockForAbstractClass(ServiceProviderInterface::class);
197
198
        $exceptionMessage = 'This is a test service provider exception message';
199
        $exceptionCode = 777;
200
        $exception = new ServiceProviderException($exceptionMessage, $exceptionCode);
201
202
        $serviceProvider->expects($this->once())
203
            ->method('registerServices')
204
            ->with($this->adapter)
205
            ->willThrowException($exception);
206
207
        $this->expectException(ContainerException::class);
208
        $this->expectExceptionMessage($exceptionMessage);
209
        $this->expectExceptionCode($exceptionCode);
210
211
        $container->registerServices($serviceProvider);
212
    }
213
214
    /**
215
     * Ensure that the service provider will have the containers adapter passed to it
216
     * when calling registerServices().
217
     *
218
     * @throws ContainerException
219
     */
220
    public function testRegisterServicesWillPassAdapterToProvidedServiceProvider(): void
221
    {
222
        $container = new Container($this->adapter);
223
224
        /** @var ServiceProviderInterface|MockObject $serviceProvider */
225
        $serviceProvider = $this->getMockForAbstractClass(ServiceProviderInterface::class);
226
227
        $serviceProvider->expects($this->once())
228
            ->method('registerServices')
229
            ->with($this->adapter);
230
231
        $container->registerServices($serviceProvider);
232
    }
233
}
234