Completed
Pull Request — 6.0 (#1895)
by nhzex
04:53
created

ContainerTest::testClosureResolution()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 13
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 6
nc 1
nop 0
dl 0
loc 13
rs 10
c 0
b 0
f 0
1
<?php
2
0 ignored issues
show
Coding Style introduced by
Missing file doc comment
Loading history...
3
namespace think\tests;
4
5
use PHPUnit\Framework\TestCase;
6
use ReflectionMethod;
7
use stdClass;
8
use think\Container;
9
use think\Exception;
10
use think\exception\ClassNotFoundException;
11
12
class Taylor
13
{
14
    public $name;
15
16
    public function __construct($name)
0 ignored issues
show
Coding Style introduced by
Missing doc comment for function __construct()
Loading history...
17
    {
18
        $this->name = $name;
19
    }
20
21
    public function some(Container $container)
0 ignored issues
show
Unused Code introduced by
The parameter $container is not used and could be removed. ( Ignorable by Annotation )

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

21
    public function some(/** @scrutinizer ignore-unused */ Container $container)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Coding Style introduced by
Missing doc comment for function some()
Loading history...
22
    {
23
24
    }
25
26
    public static function static(Container $container)
0 ignored issues
show
Coding Style introduced by
Missing doc comment for function static()
Loading history...
27
    {
28
        return $container;
29
    }
30
31
    public static function __make()
2 ignored issues
show
Coding Style introduced by
Missing doc comment for function __make()
Loading history...
Coding Style introduced by
Method name "Taylor::__make" is invalid; only PHP magic methods should be prefixed with a double underscore
Loading history...
Coding Style introduced by
Public method name "Taylor::__make" must not be prefixed with an underscore
Loading history...
32
    {
33
        return new self('Taylor');
34
    }
35
}
36
37
class SomeClass
38
{
39
    public $container;
40
41
    public function __construct(Container $container)
0 ignored issues
show
Coding Style introduced by
Missing doc comment for function __construct()
Loading history...
42
    {
43
        $this->container = $container;
44
    }
45
}
46
47
class ContainerTest extends TestCase
48
{
49
    protected function tearDown(): void
0 ignored issues
show
Coding Style introduced by
Missing doc comment for function tearDown()
Loading history...
50
    {
51
        Container::setInstance(null);
52
    }
53
54
    public function testClosureResolution()
0 ignored issues
show
Coding Style introduced by
Missing doc comment for function testClosureResolution()
Loading history...
55
    {
56
        $container = new Container;
57
58
        Container::setInstance($container);
59
60
        $container->bind('name', function () {
0 ignored issues
show
Coding Style introduced by
The opening parenthesis of a multi-line function call should be the last content on the line.
Loading history...
61
            return 'Taylor';
62
        });
0 ignored issues
show
Coding Style introduced by
For multi-line function calls, the closing parenthesis should be on a new line.

If a function call spawns multiple lines, the coding standard suggests to move the closing parenthesis to a new line:

someFunctionCall(
    $firstArgument,
    $secondArgument,
    $thirdArgument
); // Closing parenthesis on a new line.
Loading history...
63
64
        $this->assertEquals('Taylor', $container->make('name'));
65
66
        $this->assertEquals('Taylor', Container::pull('name'));
67
    }
68
69
    public function testGet()
0 ignored issues
show
Coding Style introduced by
Missing doc comment for function testGet()
Loading history...
70
    {
71
        $container = new Container;
72
73
        $this->expectException(ClassNotFoundException::class);
74
        $this->expectExceptionMessage('class not exists: name');
75
        $container->get('name');
76
77
        $container->bind('name', function () {
0 ignored issues
show
Coding Style introduced by
The opening parenthesis of a multi-line function call should be the last content on the line.
Loading history...
78
            return 'Taylor';
79
        });
0 ignored issues
show
Coding Style introduced by
For multi-line function calls, the closing parenthesis should be on a new line.

If a function call spawns multiple lines, the coding standard suggests to move the closing parenthesis to a new line:

someFunctionCall(
    $firstArgument,
    $secondArgument,
    $thirdArgument
); // Closing parenthesis on a new line.
Loading history...
80
81
        $this->assertSame('Taylor', $container->get('name'));
82
    }
83
84
    public function testExist()
0 ignored issues
show
Coding Style introduced by
Missing doc comment for function testExist()
Loading history...
85
    {
86
        $container = new Container;
87
88
        $container->bind('name', function () {
0 ignored issues
show
Coding Style introduced by
The opening parenthesis of a multi-line function call should be the last content on the line.
Loading history...
89
            return 'Taylor';
90
        });
0 ignored issues
show
Coding Style introduced by
For multi-line function calls, the closing parenthesis should be on a new line.

If a function call spawns multiple lines, the coding standard suggests to move the closing parenthesis to a new line:

someFunctionCall(
    $firstArgument,
    $secondArgument,
    $thirdArgument
); // Closing parenthesis on a new line.
Loading history...
91
92
        $this->assertFalse($container->exists("name"));
93
94
        $container->make('name');
95
96
        $this->assertTrue($container->exists('name'));
97
    }
98
99
    public function testInstance()
0 ignored issues
show
Coding Style introduced by
Missing doc comment for function testInstance()
Loading history...
100
    {
101
        $container = new Container;
102
103
        $container->bind('name', function () {
0 ignored issues
show
Coding Style introduced by
The opening parenthesis of a multi-line function call should be the last content on the line.
Loading history...
104
            return 'Taylor';
105
        });
0 ignored issues
show
Coding Style introduced by
For multi-line function calls, the closing parenthesis should be on a new line.

If a function call spawns multiple lines, the coding standard suggests to move the closing parenthesis to a new line:

someFunctionCall(
    $firstArgument,
    $secondArgument,
    $thirdArgument
); // Closing parenthesis on a new line.
Loading history...
106
107
        $this->assertEquals('Taylor', $container->get('name'));
108
109
        $container->bind('name2', Taylor::class);
110
111
        $object = new stdClass();
112
113
        $this->assertFalse($container->exists('name2'));
114
115
        $container->instance('name2', $object);
116
117
        $this->assertTrue($container->exists('name2'));
118
119
        $this->assertTrue($container->exists(Taylor::class));
120
121
        $this->assertEquals($object, $container->make(Taylor::class));
122
123
        unset($container->name1);
0 ignored issues
show
Bug Best Practice introduced by
The property name1 does not exist on think\Container. Since you implemented __get, consider adding a @property annotation.
Loading history...
124
125
        $this->assertFalse($container->exists('name1'));
126
127
        $container->delete('name2');
128
129
        $this->assertFalse($container->exists('name2'));
130
131
        foreach ($container as $class => $instance) {
132
133
        }
134
    }
135
136
    public function testBind()
0 ignored issues
show
Coding Style introduced by
Missing doc comment for function testBind()
Loading history...
137
    {
138
        $container = new Container;
139
140
        $object = new stdClass();
141
142
        $container->bind(['name' => Taylor::class]);
143
144
        $container->bind('name2', $object);
145
146
        $container->bind('name3', Taylor::class);
147
148
        $container->name4 = $object;
0 ignored issues
show
Bug Best Practice introduced by
The property name4 does not exist on think\Container. Since you implemented __set, consider adding a @property annotation.
Loading history...
149
150
        $container['name5'] = $object;
151
152
        $this->assertTrue(isset($container->name4));
0 ignored issues
show
Bug Best Practice introduced by
The property name4 does not exist on think\Container. Since you implemented __get, consider adding a @property annotation.
Loading history...
153
154
        $this->assertTrue(isset($container['name5']));
155
156
        $this->assertInstanceOf(Taylor::class, $container->get('name'));
157
158
        $this->assertSame($object, $container->get('name2'));
159
160
        $this->assertSame($object, $container->name4);
161
162
        $this->assertSame($object, $container['name5']);
163
164
        $this->assertInstanceOf(Taylor::class, $container->get('name3'));
165
166
        unset($container['name']);
167
168
        $this->assertFalse(isset($container['name']));
169
170
        unset($container->name3);
0 ignored issues
show
Bug Best Practice introduced by
The property name3 does not exist on think\Container. Since you implemented __get, consider adding a @property annotation.
Loading history...
171
172
        $this->assertFalse(isset($container->name3));
173
    }
174
175
    public function testAutoConcreteResolution()
0 ignored issues
show
Coding Style introduced by
Missing doc comment for function testAutoConcreteResolution()
Loading history...
176
    {
177
        $container = new Container;
178
179
        $taylor = $container->make(Taylor::class);
180
181
        $this->assertInstanceOf(Taylor::class, $taylor);
182
        $this->assertAttributeSame('Taylor', 'name', $taylor);
0 ignored issues
show
Deprecated Code introduced by
The function PHPUnit\Framework\Assert::assertAttributeSame() has been deprecated: https://github.com/sebastianbergmann/phpunit/issues/3338 ( Ignorable by Annotation )

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

182
        /** @scrutinizer ignore-deprecated */ $this->assertAttributeSame('Taylor', 'name', $taylor);

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
183
    }
184
185
    public function testGetAndSetInstance()
0 ignored issues
show
Coding Style introduced by
Missing doc comment for function testGetAndSetInstance()
Loading history...
186
    {
187
        $this->assertInstanceOf(Container::class, Container::getInstance());
188
189
        $object = new stdClass();
190
191
        Container::setInstance($object);
192
193
        $this->assertSame($object, Container::getInstance());
194
195
        Container::setInstance(function () {
0 ignored issues
show
Coding Style introduced by
The opening parenthesis of a multi-line function call should be the last content on the line.
Loading history...
196
            return $this;
197
        });
0 ignored issues
show
Coding Style introduced by
For multi-line function calls, the closing parenthesis should be on a new line.

If a function call spawns multiple lines, the coding standard suggests to move the closing parenthesis to a new line:

someFunctionCall(
    $firstArgument,
    $secondArgument,
    $thirdArgument
); // Closing parenthesis on a new line.
Loading history...
198
199
        $this->assertSame($this, Container::getInstance());
200
    }
201
202
    public function testInvokeFunctionWithoutMethodThrowsException()
0 ignored issues
show
Coding Style introduced by
Missing doc comment for function testInvokeFunctionWithoutMethodThrowsException()
Loading history...
203
    {
204
        $this->expectException(Exception::class);
205
        $this->expectExceptionMessage('function not exists: ContainerTestCallStub()');
206
        $container = new Container;
207
        $container->invokeFunction('ContainerTestCallStub', []);
208
    }
209
210
    public function testInvokeClosureFunctionWithoutMethodThrowsException()
0 ignored issues
show
Coding Style introduced by
Missing doc comment for function testInvokeClosureFunctionWithoutMethodThrowsException()
Loading history...
211
    {
212
        $this->expectException(Exception::class);
213
        $this->expectExceptionMessageRegExp('/function not exists: {Closure}@.+#L\d+-\d+/');
214
        $container = new Container;
215
        $container->invokeFunction(function () {
0 ignored issues
show
Coding Style introduced by
The opening parenthesis of a multi-line function call should be the last content on the line.
Loading history...
216
            throw new \ReflectionException('test exception');
217
        });
0 ignored issues
show
Coding Style introduced by
For multi-line function calls, the closing parenthesis should be on a new line.

If a function call spawns multiple lines, the coding standard suggests to move the closing parenthesis to a new line:

someFunctionCall(
    $firstArgument,
    $secondArgument,
    $thirdArgument
); // Closing parenthesis on a new line.
Loading history...
218
    }
219
220
    public function testInvoke()
0 ignored issues
show
Coding Style introduced by
Missing doc comment for function testInvoke()
Loading history...
221
    {
222
        $container = new Container();
223
224
        Container::setInstance($container);
225
226
        $container->bind(Container::class, $container);
227
228
        $stub = $this->createMock(Taylor::class);
229
230
        $stub->expects($this->once())->method('some')->with($container)->will($this->returnSelf());
231
232
        $container->invokeMethod([$stub, 'some']);
233
234
        $this->assertSame($container, $container->invokeMethod(Taylor::class . '::static'));
235
236
        $reflect = new ReflectionMethod($container, 'exists');
237
238
        $this->assertTrue($container->invokeReflectMethod($container, $reflect, [Container::class]));
239
240
        $this->assertSame($container, $container->invoke(function (Container $container) {
0 ignored issues
show
Coding Style introduced by
The opening parenthesis of a multi-line function call should be the last content on the line.
Loading history...
241
            return $container;
242
        }));
0 ignored issues
show
Coding Style introduced by
For multi-line function calls, the closing parenthesis should be on a new line.

If a function call spawns multiple lines, the coding standard suggests to move the closing parenthesis to a new line:

someFunctionCall(
    $firstArgument,
    $secondArgument,
    $thirdArgument
); // Closing parenthesis on a new line.
Loading history...
243
244
        $this->assertSame($container, $container->invoke(Taylor::class . '::static'));
245
246
        $object = $container->invokeClass(SomeClass::class);
247
        $this->assertInstanceOf(SomeClass::class, $object);
248
        $this->assertSame($container, $object->container);
249
250
        $stdClass = new stdClass();
251
252
        $container->invoke(function (Container $container, stdClass $stdObject, $key1, $lowKey, $key2 = 'default') use ($stdClass) {
0 ignored issues
show
Coding Style introduced by
The opening parenthesis of a multi-line function call should be the last content on the line.
Loading history...
253
            $this->assertEquals('value1', $key1);
254
            $this->assertEquals('default', $key2);
255
            $this->assertEquals('value2', $lowKey);
256
            $this->assertSame($stdClass, $stdObject);
257
            return $container;
258
        }, ['some' => $stdClass, 'key1' => 'value1', 'low_key' => 'value2']);
0 ignored issues
show
Coding Style introduced by
For multi-line function calls, the closing parenthesis should be on a new line.

If a function call spawns multiple lines, the coding standard suggests to move the closing parenthesis to a new line:

someFunctionCall(
    $firstArgument,
    $secondArgument,
    $thirdArgument
); // Closing parenthesis on a new line.
Loading history...
259
    }
260
261
    public function testInvokeMethodNotExists()
0 ignored issues
show
Coding Style introduced by
Missing doc comment for function testInvokeMethodNotExists()
Loading history...
262
    {
263
        $container = $this->resolveContainer();
264
        $this->expectException(Exception::class);
265
266
        $container->invokeMethod([SomeClass::class, 'any']);
267
    }
268
269
    public function testInvokeClassNotExists()
0 ignored issues
show
Coding Style introduced by
Missing doc comment for function testInvokeClassNotExists()
Loading history...
270
    {
271
        $container = new Container();
272
273
        Container::setInstance($container);
274
275
        $container->bind(Container::class, $container);
276
277
        $this->expectExceptionObject(new ClassNotFoundException('class not exists: SomeClass'));
278
279
        $container->invokeClass('SomeClass');
280
    }
281
282
    protected function resolveContainer()
0 ignored issues
show
Coding Style introduced by
Missing doc comment for function resolveContainer()
Loading history...
283
    {
284
        $container = new Container();
285
286
        Container::setInstance($container);
287
        return $container;
288
    }
289
290
}
291