Passed
Push — feature/container-extend ( d5ded5 )
by Chema
04:29 queued 29s
created

php$0 ➔ test_extend_existing_callable_service()   A

Complexity

Conditions 1

Size

Total Lines 22

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
dl 0
loc 22
rs 9.568
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)
0 ignored issues
show
Bug introduced by
function(...) { /* ... */ } of type callable is incompatible with the type object expected by parameter $service of Gacela\Framework\Container\Container::factory(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

105
                /** @scrutinizer ignore-type */ static fn () => 'value_' . random_int(0, PHP_INT_MAX)
Loading history...
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 fn (ArrayObject $arrayObject) => $arrayObject->append(4)
165
        );
166
167
        /** @var ArrayObject $actual */
168
        $actual = $this->container->get('service_name');
169
170
        self::assertEquals(new ArrayObject([1, 2, 3, 4]), $actual);
171
    }
172
173
    public function test_extend_non_existing_service(): void
174
    {
175
        $this->container->extend('service_name', static fn () => '');
176
177
        $this->expectException(ContainerKeyNotFoundException::class);
178
        $this->container->get('service_name');
179
    }
180
181
    public function test_service_not_extendable(): void
182
    {
183
        $this->container->set('service_name', 'raw string');
184
185
        $this->expectExceptionObject(ContainerException::serviceNotExtendable());
186
        $this->container->extend('service_name', static fn (string $str) => $str);
187
    }
188
}
189