Passed
Pull Request — master (#4)
by Alex
01:51
created

ContainerTest::testGetWillReturnAServiceByName()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 10
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 5
c 0
b 0
f 0
dl 0
loc 10
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\Exception\ContainerException;
8
use Arp\Container\Exception\NotFoundException;
9
use Arp\Container\Container;
10
use PHPUnit\Framework\TestCase;
11
use Psr\Container\ContainerExceptionInterface;
12
use Psr\Container\ContainerInterface;
13
use Psr\Container\NotFoundExceptionInterface;
14
15
/**
16
 * @covers \Arp\Container\Container
17
 *
18
 * @author  Alex Patterson <[email protected]>
19
 * @package ArpTest\ContainerArray
20
 */
21
final class ContainerTest extends TestCase
22
{
23
    /**
24
     * Assert that the Container implements ContainerInterface.
25
     */
26
    public function testImplementsContainerInterface(): void
27
    {
28
        $container = new Container();
29
30
        $this->assertInstanceOf(ContainerInterface::class, $container);
31
    }
32
33
    /**
34
     * Assert that has() will return true for a service that has been set on the container
35
     *
36
     * @throws ContainerExceptionInterface
37
     */
38
    public function testHasWillAssertBooleanTrueForRegisteredService(): void
39
    {
40
        $container = new Container();
41
42
        $name = \stdClass::class;
43
        $service = new \stdClass();
44
45
        $this->assertFalse($container->has($name));
46
47
        $container->set($name, $service);
48
49
        $this->assertTrue($container->has($name));
50
    }
51
52
    /**
53
     * Assert that has() will return FALSE for a service that has NOT been set on the container
54
     *
55
     * @throws ContainerExceptionInterface
56
     */
57
    public function testHasWillAssertBooleanFalseForNonRegisteredService(): void
58
    {
59
        $container = new Container();
60
61
        $name = \stdClass::class;
62
63
        $this->assertFalse($container->has($name));
64
    }
65
66
    /**
67
     * Assert that a value can be set and returned from the container.
68
     */
69
    public function testGetWillReturnAServiceByName(): void
70
    {
71
        $container = new Container();
72
73
        $name = \stdClass::class;
74
        $service = new \stdClass();
75
76
        $container->set($name, $service);
77
78
        $this->assertSame($service, $container->get($name));
79
    }
80
81
    /**
82
     * Assert that calls to get with a registered service alias will return the named service
83
     *
84
     * @throws ContainerExceptionInterface
85
     */
86
    public function testGetWillReturnAServiceByAliasName(): void
87
    {
88
        $container = new Container();
89
90
        $alias = 'foo';
91
        $name = \stdClass::class;
92
        $service = new \stdClass();
93
94
        $container->set($name, $service);
95
        $container->setAlias($alias, $name);
96
97
        $this->assertSame($service, $container->get($alias));
98
    }
99
100
    /**
101
     * Assert that the container will throw a NotFoundException if the requested service cannot be found.
102
     *
103
     * @throws NotFoundExceptionInterface
104
     */
105
    public function testGetWillThrowNotFoundExceptionIfRequestedServiceIsNotRegistered(): void
106
    {
107
        $container = new Container();
108
109
        $name = 'FooService';
110
111
        $this->expectException(NotFoundException::class);
112
        $this->expectExceptionMessage(
113
            sprintf('Service \'%s\' could not be found registered with the container', $name)
114
        );
115
116
        $container->get($name);
117
    }
118
119
    /**
120
     * Assert that a invalid/non-callable factory class will throw a ContainerException.
121
     */
122
    public function testGetWillThrowContainerExceptionIfTheRegisteredFactoryIsNotCallable(): void
123
    {
124
        $container = new Container();
125
126
        $name = 'FooService';
127
        $factoryClassName = \stdClass::class;
128
129
        $container->setFactoryClass($name, $factoryClassName);
130
131
        $this->expectException(ContainerException::class);
132
        $this->expectExceptionMessage(
133
            sprintf(
134
                'Factory \'%s\' registered for service \'%s\', must be callable',
135
                $factoryClassName,
136
                $name
137
            )
138
        );
139
140
        $container->get($name);
141
    }
142
143
    /**
144
     * Assert that circular dependencies between a service name and it's factory are resolved by throwing
145
     * a ContainerException
146
     *
147
     * @throws ContainerExceptionInterface
148
     */
149
    public function testCircularDependencyWithFactoryClassNameWillThrowContainerException(): void
150
    {
151
        $name = CallableMock::class;
152
        $factoryClassName = CallableMock::class;
153
154
        $container = new Container();
155
        $container->setFactoryClass($name, $factoryClassName);
156
157
        $this->expectException(ContainerException::class);
158
        $this->expectDeprecationMessage(
159
            sprintf('A circular configuration dependency was detected for service \'%s\'', $name)
160
        );
161
162
        $container->get($name);
163
    }
164
165
    /**
166
     * Assert that the container will throw a ContainerException is the registered factory throws an exception.
167
     */
168
    public function testFactoryCreationErrorWillBeCaughtAndRethrownAsContainerException(): void
169
    {
170
        $container = new Container();
171
172
        $name = 'FooService';
173
        $exceptionMessage = 'This is another test exception message';
174
175
        $factory = static function () use ($exceptionMessage): void {
176
            throw new \RuntimeException($exceptionMessage);
177
        };
178
179
        $container->setFactory($name, $factory);
180
181
        $this->expectException(ContainerException::class);
182
        $this->expectExceptionMessage(
183
            sprintf('The service \'%s\' could not be created: %s', $name, $exceptionMessage)
184
        );
185
186
        $container->get($name);
187
    }
188
189
    /**
190
     * Assert that an unregistered service, which resolves to the name of a valid class, will be created and
191
     * registered with the container. Additional calls to the container's get() method should also return the same
192
     * service
193
     */
194
    public function testGetWillCreateAndReturnUnregisteredServiceIfTheNameResolvesToAValidClassName(): void
195
    {
196
        $container = new Container();
197
198
        $name = \stdClass::class;
199
        $this->assertFalse($container->has($name));
200
        $service = $container->get(\stdClass::class);
201
202
        $this->assertInstanceOf($name, $service);
203
        $this->assertTrue($container->has($name));
204
        $this->assertSame($service, $container->get($name));
205
    }
206
}
207