Instantiator_creates_empty_instances::allClasses()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 3
c 0
b 0
f 0
rs 10
cc 1
eloc 1
nc 1
nop 0
1
<?php
2
declare(strict_types=1);
3
4
namespace Stratadox\Instantiator\Test;
5
6
use function array_merge;
7
use Exception;
8
use InvalidArgumentException;
9
use PHPUnit\Framework\TestCase;
10
use ReflectionClass;
11
use stdClass;
12
use Stratadox\Instantiator\NoSuchClass;
13
use Stratadox\Instantiator\InstantiationFailure;
14
use Stratadox\Instantiator\NoConcreteClass;
15
use Stratadox\Instantiator\ObjectInstantiator;
16
use Stratadox\Instantiator\Test\Fixtures\AbstractClass;
17
use Stratadox\Instantiator\Test\Fixtures\AnInterface;
18
use Stratadox\Instantiator\Test\Fixtures\ExceptionThrowingConstructor;
19
use Stratadox\Instantiator\Test\Fixtures\FinalInternal;
20
use Stratadox\Instantiator\Test\Fixtures\PrivateClone;
21
use Stratadox\Instantiator\Test\Fixtures\PrivateConstructor;
22
use Stratadox\Instantiator\Test\Fixtures\PrivateConstructorAndClone;
23
use Stratadox\Instantiator\NotAClass;
24
25
class Instantiator_creates_empty_instances extends TestCase
26
{
27
    /**
28
     * @test
29
     * @dataProvider classes
30
     */
31
    function creating_instances_without_calling_the_constructor(string $class)
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
32
    {
33
        $instance = ObjectInstantiator::forThe($class)->instance();
34
35
        self::assertInstanceOf($class, $instance);
36
    }
37
38
    /**
39
     * @test
40
     * @dataProvider classes
41
     */
42
    function creating_a_new_instance_on_each_call(string $class)
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
43
    {
44
        $instantiator = ObjectInstantiator::forThe($class);
45
46
        $instance1 = $instantiator->instance();
47
        $instance2 = $instantiator->instance();
48
49
        self::assertEquals($instance1, $instance2);
50
        self::assertNotSame($instance1, $instance2);
51
    }
52
53
    /**
54
     * @test
55
     * @dataProvider classes
56
     */
57
    function finding_out_which_class_is_instantiated(string $class)
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
58
    {
59
        self::assertEquals($class, ObjectInstantiator::forThe($class)->class());
60
    }
61
62
    /**
63
     * @test
64
     * @dataProvider illegalClasses
65
     */
66
    function throwing_an_invalid_argument_exception_when_the_class_does_not_exist(
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
67
        string $class,
68
        string $expectedClass
69
    ) {
70
        $this->expectException($expectedClass);
71
72
        ObjectInstantiator::forThe($class);
73
    }
74
75
    /**
76
     * @test
77
     * @dataProvider allClasses
78
     */
79
    function either_throwing_an_exception_in_the_constructor_or_correctly_instantiating(
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
80
        string $class,
81
        string $expectedClass = 'N/A'
82
    ) {
83
        try {
84
            $instantiator = ObjectInstantiator::forThe($class);
85
        } catch (InstantiationFailure $exception) {
86
            self::assertInstanceOf($expectedClass, $exception);
87
            return;
88
        }
89
        $instance = $instantiator->instance();
90
        self::assertInstanceOf($class, $instance);
91
    }
92
93
    public function classes(): array
94
    {
95
        return [
96
            'class with exception in the constructor'  => [ExceptionThrowingConstructor::class],
97
            'class with private clone'                 => [PrivateClone::class],
98
            'class with private constructor'           => [PrivateConstructor::class],
99
            'class with private constructor and clone' => [PrivateConstructorAndClone::class],
100
            'this test class'                          => [__CLASS__],
101
            'the basic Exception class'                => [Exception::class],
102
            'an InvalidArgumentException'              => [InvalidArgumentException::class],
103
            'the built-in stdClass'                    => [stdClass::class],
104
            'a ReflectionClass'                        => [ReflectionClass::class],
105
            'a final internal class'                   => [FinalInternal::class],
106
        ];
107
    }
108
109
    public function illegalClasses(): array
110
    {
111
        return [
112
            'non existing class' => [
113
                'non existing class',
114
                NoSuchClass::class
115
            ],
116
            'abstract class' => [
117
                AbstractClass::class,
118
                NoConcreteClass::class
119
            ],
120
            'interface' => [
121
                AnInterface::class,
122
                NotAClass::class
123
            ],
124
        ];
125
    }
126
127
    public function allClasses(): array
128
    {
129
        return array_merge($this->classes(), $this->illegalClasses());
130
    }
131
}
132