ContainerTest.php$0 ➔ __invoke()   A
last analyzed

Complexity

Conditions 1

Size

Total Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
c 1
b 0
f 0
dl 0
loc 3
rs 10
1
<?php
2
3
declare(strict_types=1);
4
5
namespace AntidotTest\Container;
6
7
use Antidot\Container\AutowiringException;
8
use Antidot\Container\Container;
9
use Antidot\Container\ContainerConfig;
10
use InvalidArgumentException;
11
use PHPUnit\Framework\TestCase;
12
use Psr\Container\ContainerInterface;
13
use Psr\Container\NotFoundExceptionInterface;
14
use SplObjectStorage;
15
use SplQueue;
16
use SplStack;
17
18
class ContainerTest extends TestCase
19
{
20
    public function testItShouldHaveConfiguredInstancesWithAutowiringEnabled(): void
21
    {
22
        $container = new Container(new ContainerConfig([
23
            'config' => [],
24
            'parameters' => [],
25
            'some.service' => SplObjectStorage::class,
26
            'some.other.service' => SplQueue::class,
27
        ]), true);
28
29
        $this->assertEquals([], $container->get('config'));
30
        $testService = $container->get('some.service');
31
        $this->assertInstanceOf(SplObjectStorage::class, $testService);
32
        $this->assertEquals($testService, $container->get('some.service'));
33
        $this->assertInstanceOf(SplQueue::class, $container->get('some.other.service'));
34
    }
35
36
    public function testItShouldHaveConfiguredInstancesFromCallablesWithOutAutowiringEnabled(): void
37
    {
38
        $container = new Container(new ContainerConfig([
39
            'config' => [],
40
            'parameters' => [],
41
            'some.service' => function (ContainerInterface $container) {
42
                $this->assertInstanceOf(Container::class, $container);
43
                return new SplObjectStorage();
44
            },
45
            'some.other.service' => new SplQueue(),
46
            'some.other.type.service' => new class
47
            {
48
                public function __invoke(ContainerInterface $container)
49
                {
50
                    return new SplStack();
51
                }
52
53
            },
54
        ]), false);
55
56
        $this->assertEquals([], $container->get('config'));
57
        $this->assertInstanceOf(SplObjectStorage::class, $container->get('some.service'));
58
        $this->assertInstanceOf(SplQueue::class, $container->get('some.other.service'));
59
        $this->assertInstanceOf(SplStack::class, $container->get('some.other.type.service'));
60
    }
61
62
    public function testItShouldKnowAllConfiguredAndLoadedServices(): void
63
    {
64
        $container = new Container(new ContainerConfig([
65
            'config' => [],
66
            'parameters' => [],
67
            'some.service' => function (ContainerInterface $container) {
68
                $this->assertInstanceOf(Container::class, $container);
69
                return new SplObjectStorage();
70
            },
71
        ]), false);
72
73
        $this->assertEquals([], $container->get('config'));
74
        $this->assertTrue($container->has('some.service'));
75
        $this->assertFalse($container->has('some.other.service'));
76
    }
77
78
    public function testItShouldDistinctBetweenFactoryAndService(): void
79
    {
80
        $container = new Container(new ContainerConfig([
81
            'config' => [],
82
            'parameters' => [
83
                'some.other.service' => [
84
                    'queue' => 'some.other.type.service',
85
                    'bar' => 'buzz',
86
                    'bazz' => ['Hello World']
87
                ],
88
            ],
89
            'some.service' => function (ContainerInterface $container) {
90
                $this->assertInstanceOf(Container::class, $container);
91
                return new SplObjectStorage();
92
            },
93
            'some.other.service' => SomeTestClass::class,
94
            'some.other.type.service' => SplQueue::class,
95
            'some.other.service.class' => SplQueue::class,
96
            'some.alias' => 'some.other.type.service',
97
            SplStack::class => SplStack::class,
98
        ]), true);
99
100
        $container->get('some.alias');
101
        $this->assertEquals([], $container->get('config'));
102
        $this->assertInstanceOf(SplObjectStorage::class, $container->get('some.service'));
103
        $this->assertInstanceOf(SplQueue::class, $container->get('some.other.type.service'));
104
        $testService = $container->get('some.other.service');
105
        $this->assertInstanceOf(SomeTestClass::class, $testService);
106
        $this->assertInstanceOf(SplQueue::class, $testService->getQueue());
107
        $this->assertInstanceOf(SplStack::class, $testService->getStack());
108
        $this->assertSame($testService->getQueue(), $container->get('some.other.type.service'));
109
        $this->assertSame($testService->getQueue(), $container->get('some.alias'));
110
        $this->assertNotSame($testService->getQueue(), $container->get('some.other.service.class'));
111
        $someTestClass2 = $container->get(SomeTestClass::class);
112
        $this->assertNotSame($testService, $someTestClass2);
113
        $this->assertSame($testService->getStack(), $someTestClass2->getStack());
114
    }
115
116
    public function testItShouldThrowExceptionWhenAreNotConfiguredInstancesOrCallablesWithOutAutowiringEnabled(): void
117
    {
118
        $this->expectException(NotFoundExceptionInterface::class);
119
120
        $container = new Container(new ContainerConfig([
121
            'config' => [],
122
            'parameters' => [],
123
            'some.service' => SplObjectStorage::class,
124
        ]), false);
125
126
        $container->get('some.service');
127
    }
128
129
    public function testItShouldThrowExceptionWhenWithAutowiringEnabled(): void
130
    {
131
        $this->expectException(AutowiringException::class);
132
133
        $container = new Container(new ContainerConfig([
134
            'config' => [],
135
            'parameters' => [],
136
        ]), true);
137
138
        $container->get(InvalidArgumentException::class);
139
    }
140
141
142
    public function testIShouldPrepareContainerToGiveADecoratedInstancesForGivenClass(): void
143
    {
144
        $container = new Container(new ContainerConfig([
145
            'config' => [],
146
            'parameters' => [],
147
            'some.service' => function () {
148
                return new\SplStack();
149
            },
150
            'some.service.delegator.factory' => function () {
151
                return function (ContainerInterface $container, string $name, callable $callback): \SplStack {
152
                    /** @var \SplStack $stack */
153
                    $stack = $callback();
154
                    $stack->push('Hello World!!!');
155
156
                    return $stack;
157
                };
158
            },
159
            'delegators' => [
160
                'some.service' => [
161
                    'some.service.delegator.factory'
162
                ]
163
            ],
164
        ]), true);
165
        /** @var \SplStack $stack */
166
        $stack = $container->get('some.service');
167
        $this->assertCount(1, $stack);
168
        $stack->rewind();
169
        $this->assertEquals('Hello World!!!', $stack->current());
170
    }
171
}
172