DependencyInjectorTest   C
last analyzed

Complexity

Total Complexity 18

Size/Duplication

Total Lines 348
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 19

Importance

Changes 0
Metric Value
dl 0
loc 348
rs 6.875
c 0
b 0
f 0
wmc 18
lcom 1
cbo 19

18 Methods

Rating   Name   Duplication   Size   Complexity  
A setUp() 0 4 1
A tearDown() 0 4 1
A testRegister() 0 11 1
A testForVariable() 0 15 1
A testWhenCreating() 0 13 1
A testForType() 0 13 1
A testFill() 0 10 1
A testWith() 0 16 1
B testCreate() 0 91 1
A testCreateCreatingInterfaceWithManyImplementationsThrowsException() 0 6 1
A testCreateCreatingNonExistingClassThrowsException() 0 4 1
A testPickFactory() 0 6 1
A testSettersFor() 0 5 1
A testWrappersFor() 0 5 1
A testUseParameters() 0 6 1
A testRepository() 0 4 1
A testInstantiateParameter() 0 15 1
A testInstantiateParameterThrowsException() 0 13 1
1
<?php
2
3
namespace KochTest\DI;
4
5
use Koch\DI\DependencyInjector;
6
use Koch\DI\Lifecycle\Reused;
7
8
class DependencyInjectorTest extends \PHPUnit_Framework_TestCase
9
{
10
    /**
11
     * @var DependencyInjector
12
     */
13
    protected $object;
14
15
    /**
16
     * Sets up the fixture, for example, opens a network connection.
17
     * This method is called before a test is executed.
18
     */
19
    protected function setUp()
20
    {
21
        $this->object = new DependencyInjector();
22
    }
23
24
    /**
25
     * Tears down the fixture, for example, closes a network connection.
26
     * This method is called after a test is executed.
27
     */
28
    protected function tearDown()
29
    {
30
        unset($this->object);
31
    }
32
33
    /**
34
     * @covers Koch\DI\DependencyInjector::register
35
     * @covers Koch\DI\DependencyInjector::instantiate
36
     * @covers Koch\DI\DependencyInjector::register
37
     */
38
    public function testRegister()
39
    {
40
        include_once __DIR__ . '/fixtures/ClassForSingletonInstantiationTest.php';
41
42
        // instantiate as singleton
43
        $this->object->register(new Reused('KochTest\DI\CreateMeOnce'));
44
        $this->assertSame(
45
            $this->object->instantiate('KochTest\DI\CreateMeOnce'),
46
            $this->object->instantiate('KochTest\DI\CreateMeOnce')
47
        );
48
    }
49
50
    /**
51
     * @covers Koch\DI\DependencyInjector::forVariable
52
     * @covers Koch\DI\DependencyInjector::register
53
     * @covers Koch\DI\DependencyInjector::instantiate
54
     * @covers Koch\DI\Engine\Variable::willUse
55
     */
56
    public function testForVariable()
57
    {
58
        include_once __DIR__ . '/fixtures/ClassesForInjectionOfVariablesTest.php';
59
60
        // test variable injection
61
        $this->object->forVariable('first')->willUse('KochTest\DI\NeededForFirst');
62
        $this->object->forVariable('second')->willUse('KochTest\DI\NeededForSecond');
63
        $this->assertEquals(
64
            $this->object->instantiate('KochTest\DI\VariablesInConstructor'),
65
            new VariablesInConstructor(
66
                new NeededForFirst(),
67
                new NeededForSecond()
68
            )
69
        );
70
    }
71
72
    /**
73
     * @covers Koch\DI\DependencyInjector::whenCreating
74
     * @covers Koch\DI\Engine\Context::wrapWith
75
     * @covers Koch\DI\DependencyInjector::instantiate
76
     */
77
    public function testWhenCreating()
78
    {
79
        include_once __DIR__ . '/fixtures/ClassesForWhenCreatingTest.php';
80
81
        // 1) create concrete implemenation BareImplemenation via interface Bare
82
        // and 2) do a constructor injection of Bare into WrapperForBare
83
        $this->object->whenCreating('KochTest\DI\Bare')->wrapWith('KochTest\DI\WrapperForBare');
84
85
        $this->assertEquals(
86
            $this->object->instantiate('KochTest\DI\Bare'),
87
            new WrapperForBare(new BareImplementation())
88
        );
89
    }
90
91
    /**
92
     * @covers Koch\DI\DependencyInjector::forType
93
     * @covers Koch\DI\Engine\Type::call
94
     * @covers Koch\DI\DependencyInjector::instantiate
95
     */
96
    public function testForType()
97
    {
98
        include_once __DIR__ . '/fixtures/ClassesForSetterInjectionTest.php';
99
100
        // test can call setters to complete initialisation
101
        $this->object->forType('KochTest\DI\NeedsInitToCompleteConstruction')->call('init');
102
        $expected = new NeedsInitToCompleteConstruction();
103
        $expected->init(new NotWithoutMe()); // <-- setter injection
104
        $this->assertEquals(
105
            $this->object->instantiate('KochTest\DI\NeedsInitToCompleteConstruction'),
106
            $expected
107
        );
108
    }
109
110
    /**
111
     * @covers Koch\DI\DependencyInjector::fill
112
     * @covers Koch\DI\DependencyInjector::with
113
     * @covers Koch\DI\DependencyInjector::instantiate
114
     */
115
    public function testFill()
116
    {
117
        include_once __DIR__ . '/fixtures/ClassForParameterInjectionTest.php';
118
119
        // can fill missing parameters with explicit values
120
        $this->assertEquals(
121
            $this->object->fill('a', 'b')->with(3, 5)->instantiate('KochTest\DI\ClassWithParameters'),
122
            new ClassWithParameters(3, 5)
123
        );
124
    }
125
126
    /**
127
     * @covers Koch\DI\DependencyInjector::with
128
     * @covers Koch\DI\DependencyInjector::fill
129
     * @covers Koch\DI\DependencyInjector::instantiate
130
     */
131
    public function testWith()
132
    {
133
        include_once __DIR__ . '/fixtures/ClassForParameterInjectionTest.php';
134
135
        // 1) can fill missing parameters with explicit values
136
        $this->assertEquals(
137
            $this->object->with(3, 5)->instantiate('KochTest\DI\ClassWithParameters'),
138
            new ClassWithParameters(3, 5)
139
        );
140
141
        // 2) can instantiate with named parameters
142
        $this->assertEquals(
143
            $this->object->fill('a', 'b')->with(3, 5)->instantiate('KochTest\DI\ClassWithParameters'),
144
            new ClassWithParameters(3, 5)
145
        );
146
    }
147
148
    /**
149
     * @covers Koch\DI\DependencyInjector::instantiate
150
     * @covers Koch\DI\DependencyInjector::instantiate
151
     * @covers Koch\DI\DependencyInjector::register
152
     * @covers Koch\DI\DependencyInjector::forVariable
153
     * @covers Koch\DI\DependencyInjector::forType
154
     * @covers Koch\DI\Engine\Type::call
155
     * @covers Koch\DI\Engine\Variable::willUse
156
     */
157
    public function testCreate()
158
    {
159
        include_once __DIR__ . '/fixtures/ClassesForInjectionOfTypeHintsTest.php';
160
161
        // test injection of simple dependencies
162
        $this->assertEquals(
163
            $this->object->instantiate('KochTest\DI\HintedConstructor'),
164
            new HintedConstructor(
165
                new NeededForConstructor()
166
            )
167
        );
168
169
        // test repeated type hint injection
170
        $this->object->register('KochTest\DI\SecondImplementation');
171
        $this->assertEquals(
172
            $this->object->instantiate('KochTest\DI\RepeatedHintConstructor'),
173
            new RepeatedHintConstructor(
174
                new NeededForConstructor(),
175
                new NeededForConstructor()
176
            )
177
        );
178
179
        include_once __DIR__ . '/fixtures/ClassForParameterInjectionTest.php';
180
181
        // test create with parameters
182
        // this is a short syntax form of the test #1 in testWith()
183
        $this->assertEquals(
184
            $this->object->instantiate('KochTest\DI\ClassWithParameters', 3, 5),
185
            new ClassWithParameters(3, 5)
186
        );
187
188
        include_once __DIR__ . '/fixtures/ClassForInjectionOfSpecificValuesTest.php';
189
190
        // test inject specific instance
191
        $this->object->register(new Thing());
192
        $this->assertEquals(
193
            $this->object->instantiate('KochTest\DI\WrapThing'),
194
            new WrapThing(new Thing())
195
        );
196
197
        // test injecting specific instance for named variable
198
        $this->object->forVariable('thing')->willUse(new Thing());
199
        $this->assertEquals(
200
            $this->object->instantiate('KochTest\DI\WrapAnything'),
201
            new WrapAnything(new Thing())
202
        );
203
204
        // test injecting non-object
205
        $this->object->forVariable('thing')->willUse(100);
206
        $this->assertEquals(
207
            $this->object->instantiate('KochTest\DI\WrapAnything'),
208
            new WrapAnything(100)
209
        );
210
211
        // test injection string @todo
212
        /* $this->object->forVariable('thing')->useString('100');
0 ignored issues
show
Unused Code Comprehensibility introduced by
68% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
213
          $this->assertEquals(
214
          $this->object->instantiate('KochTest\DI\WrapAnything'), new WrapAnything('100')
215
          ); */
216
217
        include_once __DIR__ . '/fixtures/ClassesForAutoInstantiationTest.php';
218
219
        // test named class instantiated automatically
220
        $this->assertInstanceOf('KochTest\DI\LoneClass', $this->object->instantiate('KochTest\DI\LoneClass'));
221
222
        // test will use only subclass if parent class is abstract class
223
        $this->assertInstanceOf(
224
            'KochTest\DI\ConcreteSubclass',
225
            $this->object->instantiate('KochTest\DI\AbstractClass')
226
        );
227
228
        // test can be configured to prefer a specific subclass
229
        $this->object->register('KochTest\DI\SecondSubclass');
230
        $this->assertInstanceOf(
231
            'KochTest\DI\SecondSubclass',
232
            $this->object->instantiate('KochTest\DI\ClassWithManySubclasses')
233
        );
234
235
        include_once __DIR__ . '/fixtures/ClassesForInterfaceInstantiationTest.php';
236
237
        $this->assertInstanceOf(
238
            'KochTest\DI\OnlyImplementation', $this->object->instantiate('KochTest\DI\InterfaceWithOneImplementation')
239
        );
240
241
        // can be configured to prefer specific implementation
242
        $this->object->register('KochTest\DI\SecondImplementation');
243
        $this->assertInstanceOf(
244
            'KochTest\DI\SecondImplementation',
245
            $this->object->instantiate('KochTest\DI\InterfaceWithManyImplementations')
246
        );
247
    }
248
249
    /**
250
     * @covers Koch\DI\DependencyInjector::instantiate
251
     * @expectedException Koch\DI\Exception\CannotFindImplementation
252
     * @expectedExceptionMessage InterfaceWithManyImplementations
253
     */
254
    public function testCreateCreatingInterfaceWithManyImplementationsThrowsException()
255
    {
256
        include_once __DIR__ . '/fixtures/ClassesForInterfaceInstantiationTest.php';
257
258
        $this->object->instantiate('InterfaceWithManyImplementations');
259
    }
260
261
    /**
262
     * @covers Koch\DI\DependencyInjector::instantiate
263
     * @expectedException Koch\DI\Exception\CannotFindImplementation
264
     * @expectedExceptionMessage NonExistingClass
265
     */
266
    public function testCreateCreatingNonExistingClassThrowsException()
267
    {
268
        $this->object->instantiate('NonExistingClass');
269
    }
270
271
    /**
272
     * @covers Koch\DI\DependencyInjector::pickFactory
273
     * @expectedException \Koch\DI\Exception\CannotDetermineImplementation
274
     */
275
    public function testPickFactory()
276
    {
277
        $type       = '';
278
        $candidates = '';
279
        $this->object->pickFactory($type, $candidates);
280
    }
281
282
    /**
283
     * @covers Koch\DI\DependencyInjector::settersFor
284
     */
285
    public function testSettersFor()
286
    {
287
        $class = '';
288
        $this->assertEquals([], $this->object->settersFor($class));
289
    }
290
291
    /**
292
     * @covers Koch\DI\DependencyInjector::wrappersFor
293
     */
294
    public function testWrappersFor()
295
    {
296
        $type = '';
297
        $this->assertEquals([], $this->object->wrappersFor($type));
298
    }
299
300
    /**
301
     * @covers Koch\DI\DependencyInjector::useParameters
302
     */
303
    public function testUseParameters()
304
    {
305
        $parameters = ['A' => '1'];
306
        $this->object->useParameters($parameters);
307
        $this->assertEquals($parameters, $this->object->named_parameters);
308
    }
309
310
    /**
311
     * @covers Koch\DI\DependencyInjector::instantiateParameter
312
     */
313
    public function testInstantiateParameter()
314
    {
315
        // prepare param 1
316
        $parameter = $this->getMock('parameter', ['getName']);
317
        // Calling $parameter->getName() will now return 'name'.
0 ignored issues
show
Unused Code Comprehensibility introduced by
36% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
318
        $parameter->expects($this->any())->method('getName')->will($this->returnValue('name'));
319
        // prepare param 2
320
        $nesting = '';
321
        // prepare class
322
        $this->object->named_parameters['name'] = 'someValue';
323
324
        $erv = $this->object->instantiateParameter($parameter, $nesting);
325
326
        $this->assertEquals('someValue', $erv);
327
    }
328
329
    /**
330
     * @covers Koch\DI\DependencyInjector::instantiateParameter
331
     * @expectedException Koch\DI\Exception\MissingDependency
332
     * @expectedExceptionMessage theMissingDependency
333
     */
334
    public function testInstantiateParameterThrowsException()
335
    {
336
        // prepare param 1
337
        $parameter = $this->getMock('parameter', ['getName']);
338
        // Calling $parameter->getName() will now return 'name'.
0 ignored issues
show
Unused Code Comprehensibility introduced by
36% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
339
        $parameter->expects($this->any())->method('getName')->will($this->returnValue('theMissingDependency'));
340
        // prepare param 2
341
        $nesting = '';
342
343
        $erv = $this->object->instantiateParameter($parameter, $nesting);
344
345
        $this->assertEquals('someValue', $erv);
346
    }
347
348
    /**
349
     * @covers Koch\DI\DependencyInjector::repository
350
     */
351
    public function testRepository()
352
    {
353
        $this->assertEquals($this->object->repository, $this->object->repository());
354
    }
355
}
356