Passed
Push — master ( 71ac2a...8d79cc )
by Dmitriy
02:35
created

testGetContainerItself()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 9
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 5
nc 1
nop 0
dl 0
loc 9
rs 10
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Yii\Debug\Tests\Unit\Collector;
6
7
use PHPUnit\Framework\TestCase;
8
use Psr\Container\ContainerExceptionInterface;
9
use Psr\Container\ContainerInterface;
10
use Psr\EventDispatcher\EventDispatcherInterface;
11
use Psr\EventDispatcher\ListenerProviderInterface;
12
use Psr\Log\LoggerInterface;
13
use Psr\Log\NullLogger;
14
use stdClass;
15
use Yiisoft\Di\Container;
16
use Yiisoft\Di\ContainerConfig;
17
use Yiisoft\EventDispatcher\Dispatcher\Dispatcher;
18
use Yiisoft\EventDispatcher\Provider\Provider;
19
use Yiisoft\Files\FileHelper;
20
use Yiisoft\Yii\Debug\Collector\CollectorInterface;
21
use Yiisoft\Yii\Debug\Collector\ContainerInterfaceProxy;
22
use Yiisoft\Yii\Debug\Collector\ContainerProxyConfig;
23
use Yiisoft\Yii\Debug\Collector\EventCollector;
24
use Yiisoft\Yii\Debug\Collector\EventDispatcherInterfaceProxy;
25
use Yiisoft\Yii\Debug\Collector\LogCollector;
26
use Yiisoft\Yii\Debug\Collector\LoggerInterfaceProxy;
27
use Yiisoft\Yii\Debug\Collector\ServiceCollector;
28
use Yiisoft\Yii\Debug\Collector\TimelineCollector;
29
30
class ContainerInterfaceProxyTest extends TestCase
31
{
32
    private string $path = 'tests/container-proxy';
33
34
    protected function tearDown(): void
35
    {
36
        parent::tearDown();
37
        FileHelper::removeDirectory($this->path);
38
    }
39
40
    public function testImmutability(): void
41
    {
42
        $containerProxy = new ContainerInterfaceProxy(new Container(ContainerConfig::create()), new ContainerProxyConfig());
43
44
        $this->assertNotSame(
45
            $containerProxy,
46
            $containerProxy->withDecoratedServices(
47
                [
48
                    LoggerInterface::class => [LoggerInterfaceProxy::class, LogCollector::class],
49
                ]
50
            )
51
        );
52
    }
53
54
    public function testGetAndHas(): void
55
    {
56
        $containerProxy = new ContainerInterfaceProxy($this->getContainer(), $this->getConfig());
57
58
        $this->assertTrue($containerProxy->isActive());
59
        $this->assertTrue($containerProxy->has(LoggerInterface::class));
60
        $this->assertInstanceOf(LoggerInterfaceProxy::class, $containerProxy->get(LoggerInterface::class));
61
    }
62
63
    public function testGetAndHasWithCallableServices(): void
64
    {
65
        $dispatcherMock = $this->getMockBuilder(EventDispatcherInterface::class)->getMock();
66
        $config = new ContainerProxyConfig(
67
            true,
68
            [
69
                LoggerInterface::class => fn (ContainerInterface $container) => $container->get(LoggerInterfaceProxy::class),
70
                EventDispatcherInterface::class => [
71
                    EventDispatcherInterfaceProxy::class,
72
                    EventCollector::class,
73
                ],
74
            ],
75
            $dispatcherMock,
76
            $this->createServiceCollector(),
77
            $this->path,
78
            1
79
        );
80
        $containerProxy = new ContainerInterfaceProxy($this->getContainer(), $config);
81
82
        $this->assertTrue($containerProxy->isActive());
83
        $this->assertTrue($containerProxy->has(LoggerInterface::class));
84
85
        $containerProxy->get(LogCollector::class)->startup();
86
        $containerProxy->get(LoggerInterface::class)->log('test', 'test message');
87
        $this->assertNotEmpty($containerProxy->get(LogCollector::class)->getCollected());
88
    }
89
90
    public function testGetWithArrayConfigWithStringKeys(): void
91
    {
92
        $dispatcherMock = $this->getMockBuilder(EventDispatcherInterface::class)->getMock();
93
        $serviceCollector = $this->createServiceCollector();
94
        $serviceCollector->startup(); // activate collector
95
96
        $config = new ContainerProxyConfig(
97
            true,
98
            [
99
                LoggerInterface::class => ['logger' => LoggerInterfaceProxy::class],
100
                EventDispatcherInterface::class => [
101
                    EventDispatcherInterfaceProxy::class,
102
                    EventCollector::class,
103
                ],
104
            ],
105
            $dispatcherMock,
106
            $serviceCollector,
107
            $this->path,
108
            1
109
        );
110
        $container = $this->getContainer();
111
        $containerProxy = new ContainerInterfaceProxy($container, $config);
112
113
        $this->assertTrue($containerProxy->isActive());
114
        $this->assertInstanceOf(LoggerInterface::class, $containerProxy->get(LoggerInterface::class));
115
116
        $containerProxy->get(LoggerInterface::class)->log('test', 'test message');
117
        $this->assertInstanceOf(LoggerInterface::class, $containerProxy->get(LoggerInterface::class));
118
        $this->assertNotEmpty($config->getCollector()->getCollected());
119
    }
120
121
    public function testGetWithoutConfig(): void
122
    {
123
        $dispatcherMock = $this->getMockBuilder(EventDispatcherInterface::class)->getMock();
124
        $config = new ContainerProxyConfig(
125
            true,
126
            [
127
                LoggerInterface::class => [LoggerInterfaceProxy::class, LogCollector::class],
128
                EventDispatcherInterface::class,
129
            ],
130
            $dispatcherMock,
131
            $this->createServiceCollector(),
132
            $this->path,
133
            1
134
        );
135
        $containerProxy = new ContainerInterfaceProxy($this->getContainer(), $config);
136
137
        $this->assertInstanceOf(EventDispatcherInterface::class, $containerProxy->get(EventDispatcherInterface::class));
138
        $this->assertInstanceOf(
139
            stdClass::class,
140
            $containerProxy->get(EventDispatcherInterface::class)->dispatch(new stdClass())
141
        );
142
    }
143
144
    public function testGetAndHasWithWrongId(): void
145
    {
146
        $containerProxy = new ContainerInterfaceProxy($this->getContainer(), $this->getConfig());
147
148
        $this->assertFalse($containerProxy->has(CollectorInterface::class));
149
150
        $this->expectException(ContainerExceptionInterface::class);
151
        $this->expectExceptionMessage(
152
            sprintf(
153
                'No definition or class found or resolvable for "%s" while building "%s".',
154
                CollectorInterface::class,
155
                CollectorInterface::class
156
            )
157
        );
158
        $containerProxy->get(CollectorInterface::class);
159
    }
160
161
    public function testGetContainerItself(): void
162
    {
163
        $containerProxy = new ContainerInterfaceProxy($this->getContainer(), $this->getConfig());
164
165
        $this->assertTrue($containerProxy->has(ContainerInterface::class));
166
167
        $container = $containerProxy->get(ContainerInterface::class);
168
        $this->assertNotNull($container);
169
        $this->assertInstanceOf(ContainerInterface::class, $container);
170
    }
171
172
    public function testGetAndHasWithNotService(): void
173
    {
174
        $containerProxy = new ContainerInterfaceProxy($this->getContainer(), $this->getConfig());
175
176
        $this->assertTrue($containerProxy->has(ListenerProviderInterface::class));
177
        $this->assertNotNull($containerProxy->get(ListenerProviderInterface::class));
178
        $this->assertInstanceOf(
179
            ListenerProviderInterface::class,
180
            $containerProxy->get(ListenerProviderInterface::class)
181
        );
182
    }
183
184
    private function getConfig(): ContainerProxyConfig
185
    {
186
        $dispatcherMock = $this->getMockBuilder(EventDispatcherInterface::class)->getMock();
187
188
        return new ContainerProxyConfig(
189
            true,
190
            [
191
                LoggerInterface::class => [LoggerInterfaceProxy::class, LogCollector::class],
192
                EventDispatcherInterface::class => [
193
                    EventDispatcherInterfaceProxy::class,
194
                    EventCollector::class,
195
                ],
196
            ],
197
            $dispatcherMock,
198
            $this->createServiceCollector(),
199
            $this->path,
200
            1
201
        );
202
    }
203
204
    private function getContainer(): Container
205
    {
206
        $config = ContainerConfig::create()
207
            ->withDefinitions([
208
                EventDispatcherInterface::class => Dispatcher::class,
209
                ListenerProviderInterface::class => Provider::class,
210
                LoggerInterface::class => NullLogger::class,
211
                LogCollector::class => LogCollector::class,
212
                EventCollector::class => EventCollector::class,
213
            ]);
214
        return new Container($config);
215
    }
216
217
    protected function createServiceCollector(): ServiceCollector
218
    {
219
        return new ServiceCollector(new TimelineCollector());
220
    }
221
}
222