Passed
Push — feature/233-frozen-used-servic... ( 09599e )
by Chema
04:50
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 function (ArrayObject $arrayObject): void {
199
                $arrayObject->append(3);
200
            }
201
        );
202
203
        /** @var ArrayObject $actual */
204
        $actual = $this->container->get('service_name');
205
206
        self::assertEquals(new ArrayObject([1, 2, 3]), $actual);
207
    }
208
209
    public function test_extend_existing_used_callable_service_then_error(): void
210
    {
211
        $this->container->set('service_name', static fn () => new ArrayObject([1, 2]));
212
        $this->container->get('service_name'); // and get frozen
213
214
        $this->expectExceptionObject(ContainerException::serviceFrozen('service_name'));
215
216
        $this->container->extend(
217
            'service_name',
218
            static function (ArrayObject $arrayObject): void {
219
                $arrayObject->append(3);
220
            }
221
        );
222
    }
223
224
    public function test_extend_later_existing_frozen_object_service_then_error(): void
225
    {
226
        $this->container->extend(
227
            'service_name',
228
            static function (ArrayObject $arrayObject): void {
229
                $arrayObject->append(3);
230
            }
231
        );
232
233
        $this->container->set('service_name', new ArrayObject([1, 2]));
234
        $this->container->get('service_name'); // and get frozen
235
236
        $this->expectExceptionObject(ContainerException::serviceFrozen('service_name'));
237
        $this->container->extend(
238
            'service_name',
239
            static function (ArrayObject $arrayObject): void {
240
                $arrayObject->append(4);
241
            }
242
        );
243
    }
244
245
    public function test_extend_later_existing_frozen_callable_service_then_error(): void
246
    {
247
        $this->container->extend(
248
            'service_name',
249
            static function (ArrayObject $arrayObject): void {
250
                $arrayObject->append(3);
251
            }
252
        );
253
254
        $this->container->set('service_name', static fn () => new ArrayObject([1, 2]));
255
        $this->container->get('service_name'); // and get frozen
256
        $this->expectExceptionObject(ContainerException::serviceFrozen('service_name'));
257
        $this->container->set('service_name', static fn () => new ArrayObject([1, 2]));
258
259
        $this->container->extend(
260
            'service_name',
261
            static function (ArrayObject $arrayObject): void {
262
                $arrayObject->append(4);
263
            }
264
        );
265
    }
266
267
    public function test_set_existing_frozen_service(): void
268
    {
269
        $this->container->set('service_name', static fn () => new ArrayObject([1, 2]));
270
        $this->container->get('service_name'); // and get frozen
271
272
        $this->expectExceptionObject(ContainerException::serviceFrozen('service_name'));
273
        $this->container->set('service_name', static fn () => new ArrayObject([3]));
274
    }
275
}
276