Passed
Pull Request — master (#234)
by Chema
03:23
created

php$0 ➔ test_set_existing_frozen_service()   A

Complexity

Conditions 1

Size

Total Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
dl 0
loc 7
rs 10
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace GacelaTest\Unit\Framework\Container;
6
7
use ArrayObject;
8
use Gacela\Framework\Container\Container;
9
use Gacela\Framework\Container\Exception\ContainerException;
10
use Gacela\Framework\Container\Exception\ContainerKeyNotFoundException;
11
use PHPUnit\Framework\TestCase;
12
use stdClass;
13
14
final class ContainerTest extends TestCase
15
{
16
    private Container $container;
17
18
    public function setUp(): void
19
    {
20
        $this->container = new Container();
21
    }
22
23
    public function test_get_non_existing_service(): void
24
    {
25
        $this->expectException(ContainerKeyNotFoundException::class);
26
        $this->container->get('unknown-service_name');
27
    }
28
29
    public function test_has_service(): void
30
    {
31
        $this->container->set('service_name', 'value');
32
33
        self::assertTrue($this->container->has('service_name'));
34
        self::assertFalse($this->container->has('unknown-service_name'));
35
    }
36
37
    public function test_remove_existing_service(): void
38
    {
39
        $this->container->set('service_name', 'value');
40
        $this->container->remove('service_name');
41
42
        $this->expectException(ContainerKeyNotFoundException::class);
43
        $this->container->get('service_name');
44
    }
45
46
    public function test_resolve_service_as_raw_string(): void
47
    {
48
        $this->container->set('service_name', 'value');
49
50
        $resolvedService = $this->container->get('service_name');
51
        self::assertSame('value', $resolvedService);
52
53
        $cachedResolvedService = $this->container->get('service_name');
54
        self::assertSame('value', $cachedResolvedService);
55
    }
56
57
    public function test_resolve_service_as_function(): void
58
    {
59
        $this->container->set('service_name', static fn (): string => 'value');
60
61
        $resolvedService = $this->container->get('service_name');
62
        self::assertSame('value', $resolvedService);
63
64
        $cachedResolvedService = $this->container->get('service_name');
65
        self::assertSame('value', $cachedResolvedService);
66
    }
67
68
    public function test_resolve_service_as_callable_class(): void
69
    {
70
        $this->container->set(
71
            'service_name',
72
            new class() {
73
                public function __invoke(): string
74
                {
75
                    return 'value';
76
                }
77
            }
78
        );
79
80
        $resolvedService = $this->container->get('service_name');
81
        self::assertSame('value', $resolvedService);
82
83
        $cachedResolvedService = $this->container->get('service_name');
84
        self::assertSame('value', $cachedResolvedService);
85
    }
86
87
    public function test_resolve_non_factory_service_with_random(): void
88
    {
89
        $this->container->set(
90
            'service_name',
91
            static fn () => 'value_' . random_int(0, PHP_INT_MAX)
92
        );
93
94
        self::assertSame(
95
            $this->container->get('service_name'),
96
            $this->container->get('service_name')
97
        );
98
    }
99
100
    public function test_resolve_factory_service_with_random(): void
101
    {
102
        $this->container->set(
103
            'service_name',
104
            $this->container->factory(
105
                static fn () => 'value_' . random_int(0, PHP_INT_MAX)
106
            )
107
        );
108
109
        self::assertNotSame(
110
            $this->container->get('service_name'),
111
            $this->container->get('service_name')
112
        );
113
    }
114
115
    public function test_resolve_factory_service_not_invokable(): void
116
    {
117
        $this->expectExceptionObject(ContainerException::serviceNotInvokable());
118
119
        $this->container->set(
120
            'service_name',
121
            $this->container->factory(new stdClass())
122
        );
123
    }
124
125
    public function test_extend_existing_callable_service(): void
126
    {
127
        $this->container->set('n3', 3);
128
        $this->container->set('service_name', static fn () => new ArrayObject([1, 2]));
129
130
        $this->container->extend(
131
            'service_name',
132
            static function (ArrayObject $arrayObject, Container $container) {
133
                $arrayObject->append($container->get('n3'));
134
                return $arrayObject;
135
            }
136
        );
137
138
        $this->container->extend(
139
            'service_name',
140
            static fn (ArrayObject $arrayObject) => $arrayObject->append(4)
141
        );
142
143
        /** @var ArrayObject $actual */
144
        $actual = $this->container->get('service_name');
145
146
        self::assertEquals(new ArrayObject([1, 2, 3, 4]), $actual);
147
    }
148
149
    public function test_extend_existing_object_service(): void
150
    {
151
        $this->container->set('n3', 3);
152
        $this->container->set('service_name', new ArrayObject([1, 2]));
153
154
        $this->container->extend(
155
            'service_name',
156
            static function (ArrayObject $arrayObject, Container $container) {
157
                $arrayObject->append($container->get('n3'));
158
                return $arrayObject;
159
            }
160
        );
161
162
        $this->container->extend(
163
            'service_name',
164
            static function (ArrayObject $arrayObject): void {
165
                $arrayObject->append(4);
166
            }
167
        );
168
169
        /** @var ArrayObject $actual */
170
        $actual = $this->container->get('service_name');
171
172
        self::assertEquals(new ArrayObject([1, 2, 3, 4]), $actual);
173
    }
174
175
    public function test_extend_non_existing_service(): void
176
    {
177
        $this->container->extend('service_name', static fn () => '');
178
179
        $this->expectException(ContainerKeyNotFoundException::class);
180
        $this->container->get('service_name');
181
    }
182
183
    public function test_service_not_extendable(): void
184
    {
185
        $this->container->set('service_name', 'raw string');
186
187
        $this->expectExceptionObject(ContainerException::serviceNotExtendable());
188
        $this->container->extend('service_name', static fn (string $str) => $str);
189
    }
190
191
    public function test_extend_existing_used_object_service_is_allowed(): void
192
    {
193
        $this->container->set('service_name', new ArrayObject([1, 2]));
194
        $this->container->get('service_name'); // not frozen because it's an object
195
196
        $this->container->extend(
197
            'service_name',
198
            static fn (ArrayObject $arrayObject) => $arrayObject->append(3)
199
        );
200
201
        /** @var ArrayObject $actual */
202
        $actual = $this->container->get('service_name');
203
204
        self::assertEquals(new ArrayObject([1, 2, 3]), $actual);
205
    }
206
207
    public function test_extend_existing_used_callable_service_then_error(): void
208
    {
209
        $this->container->set('service_name', static fn () => new ArrayObject([1, 2]));
210
        $this->container->get('service_name'); // and get frozen
211
212
        $this->expectExceptionObject(ContainerException::serviceFrozen('service_name'));
213
214
        $this->container->extend(
215
            'service_name',
216
            static fn (ArrayObject $arrayObject) => $arrayObject->append(3)
217
        );
218
    }
219
220
    public function test_extend_later_existing_frozen_object_service_then_error(): void
221
    {
222
        $this->container->extend(
223
            'service_name',
224
            static fn (ArrayObject $arrayObject) => $arrayObject->append(3)
225
        );
226
227
        $this->container->set('service_name', new ArrayObject([1, 2]));
228
        $this->container->get('service_name'); // and get frozen
229
230
        $this->expectExceptionObject(ContainerException::serviceFrozen('service_name'));
231
232
        $this->container->extend(
233
            'service_name',
234
            static fn (ArrayObject $arrayObject) => $arrayObject->append(4)
235
        );
236
    }
237
238
    public function test_extend_later_existing_frozen_callable_service_then_error(): void
239
    {
240
        $this->container->extend(
241
            'service_name',
242
            static fn (ArrayObject $arrayObject) => $arrayObject->append(3)
243
        );
244
245
        $this->container->set('service_name', static fn () => new ArrayObject([1, 2]));
246
        $this->container->get('service_name'); // and get frozen
247
248
        $this->expectExceptionObject(ContainerException::serviceFrozen('service_name'));
249
250
        $this->container->extend(
251
            'service_name',
252
            static fn (ArrayObject $arrayObject) => $arrayObject->append(4)
253
        );
254
    }
255
256
    public function test_set_existing_frozen_service(): void
257
    {
258
        $this->container->set('service_name', static fn () => new ArrayObject([1, 2]));
259
        $this->container->get('service_name'); // and get frozen
260
261
        $this->expectExceptionObject(ContainerException::serviceFrozen('service_name'));
262
        $this->container->set('service_name', static fn () => new ArrayObject([3]));
263
    }
264
}
265