Issues (4)

src/PlatineTestCase.php (4 issues)

1
<?php
2
3
/**
4
 * Platine Test Tools
5
 *
6
 * Platine Test Tools is a collection of some classes/functions designed for tests
7
 *
8
 * This content is released under the MIT License (MIT)
9
 *
10
 * Copyright (c) 2020 Platine Test Tools
11
 *
12
 * Permission is hereby granted, free of charge, to any person obtaining a copy
13
 * of this software and associated documentation files (the "Software"), to deal
14
 * in the Software without restriction, including without limitation the rights
15
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
16
 * copies of the Software, and to permit persons to whom the Software is
17
 * furnished to do so, subject to the following conditions:
18
 *
19
 * The above copyright notice and this permission notice shall be included in all
20
 * copies or substantial portions of the Software.
21
 *
22
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
25
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
28
 * SOFTWARE.
29
 */
30
31
/**
32
 *  @file PlatineTestCase.php
33
 *
34
 *  The Base class used for test case
35
 *
36
 *  @package    Platine
37
 *  @author Platine Developers Team
38
 *  @copyright  Copyright (c) 2020
39
 *  @license    http://opensource.org/licenses/MIT  MIT License
40
 *  @link   http://www.iacademy.cf
41
 *  @version 1.0.0
42
 *  @filesource
43
 */
44
45
declare(strict_types=1);
46
47
namespace Platine;
48
49
use InvalidArgumentException;
50
use org\bovigo\vfs\vfsStream;
51
use org\bovigo\vfs\vfsStreamContainer;
52
use org\bovigo\vfs\vfsStreamDirectory;
53
use org\bovigo\vfs\vfsStreamFile;
54
use org\bovigo\vfs\vfsStreamContainerIterator;
55
use PHPUnit\Framework\TestCase;
56
use ReflectionClass;
57
use ReflectionProperty;
58
59
class PlatineTestCase extends TestCase
60
{
61
62
    /**
63
     * @codeCoverageIgnore
64
     * @return void
65
     */
66
    protected function tearDown(): void
67
    {
68
        //restore all mock variable global value to "false"
69
        foreach ($GLOBALS as $key => $value) {
70
            if (substr((string) $key, 0, 5) === 'mock_') {
71
                $GLOBALS[$key] = false;
72
            }
73
        }
74
    }
75
76
    /**
77
     * Method to test private & protected method
78
     *
79
     * @param object $object the class instance to use
80
     * @param string $method the name of the method
81
     * @param array<int, mixed> $args the list of method arguments
82
     * @return mixed
83
     */
84
    public function runPrivateProtectedMethod(
85
        object $object,
86
        string $method,
87
        array $args = []
88
    ) {
89
        $reflection = new ReflectionClass(get_class($object));
90
        $reflectionMethod = $reflection->getMethod($method);
91
        $reflectionMethod->setAccessible(true);
92
        return $reflectionMethod->invokeArgs($object, $args);
93
    }
94
95
    /**
96
     * Method to set/get private & protected attribute
97
     *
98
     * @param string $className the name of the class
99
     * @param string $attr the name of the class attribute
100
     */
101
    public function getPrivateProtectedAttribute(
102
        string $className,
103
        string $attr
104
    ): ReflectionProperty {
105
        $rProp = new ReflectionProperty($className, $attr);
106
        $rProp->setAccessible(true);
107
        return $rProp;
108
    }
109
110
    /**
111
     * Create virtual file with the given content
112
     * @param  string $filename
113
     * @param  vfsStreamContainer<vfsStreamContainerIterator> $destination
114
     * @param  string $content
115
     * @return vfsStreamFile
116
     */
117
    public function createVfsFile(
118
        string $filename,
119
        vfsStreamContainer $destination,
120
        string $content = ''
121
    ): vfsStreamFile {
122
        return vfsStream::newFile($filename)
123
                        ->at($destination)
124
                        ->setContent($content);
125
    }
126
127
    /**
128
     * Create virtual file without content
129
     * @param  string $filename
130
     * @param  vfsStreamContainer<vfsStreamContainerIterator> $destination
131
     * @return vfsStreamFile
132
     */
133
    public function createVfsFileOnly(
134
        string $filename,
135
        vfsStreamContainer $destination
136
    ): vfsStreamFile {
137
        return vfsStream::newFile($filename)
138
                        ->at($destination);
139
    }
140
141
    /**
142
     * Create virtual directory
143
     * @param  string $name
144
     * @param  vfsStreamContainer<vfsStreamContainerIterator> $destination
145
     * @return vfsStreamDirectory
146
     */
147
    public function createVfsDirectory(
148
        string $name,
149
        vfsStreamContainer $destination = null
150
    ): vfsStreamDirectory {
151
        if ($destination) {
152
            return vfsStream::newDirectory($name)->at($destination);
153
        }
154
        return vfsStream::newDirectory($name);
155
    }
156
157
    /**
158
     * Return the list of methods to mocks in the parameters of PHPUnit::TestCase::getMock()
159
     *
160
     * @param class-string<object>|object $class
0 ignored issues
show
Documentation Bug introduced by
The doc comment class-string<object>|object at position 0 could not be parsed: Unknown type name 'class-string' at position 0 in class-string<object>|object.
Loading history...
161
     * @param string[] $exclude list of methods to exclude
162
     * @return string[]
163
     */
164
    public function getClassMethodsToMock($class, array $exclude = []): array
165
    {
166
        $methods = [];
167
168
        if (is_string($class) && !class_exists($class)) {
169
            throw new InvalidArgumentException(
170
                sprintf('Can not find class [%s]', $class)
171
            );
172
        }
173
174
        $reflectionClass = new ReflectionClass($class);
175
176
        foreach ($reflectionClass->getMethods() as $reflectionMethod) {
177
            if (!in_array($reflectionMethod->name, $exclude)) {
178
                $methods[] = $reflectionMethod->name;
179
            }
180
        }
181
182
        return $methods;
183
    }
184
185
    /**
186
     * Get the instance of the given class
187
     * @param class-string $class
0 ignored issues
show
Documentation Bug introduced by
The doc comment class-string at position 0 could not be parsed: Unknown type name 'class-string' at position 0 in class-string.
Loading history...
188
     * @param array<string, mixed> $mockMethods
189
     * @param array<int, string> $excludes
190
     * @return mixed
191
     */
192
    public function getMockInstance(
193
        string $class,
194
        array $mockMethods = [],
195
        array $excludes = []
196
    ) {
197
        $methods = $this->getClassMethodsToMock($class, $excludes);
198
199
        $mock = $this->getMockBuilder($class)
200
                    ->disableOriginalConstructor()
201
                    ->onlyMethods($methods)
202
                    ->getMock();
203
204
        foreach ($mockMethods as $method => $returnValue) {
205
            $mock->expects($this->any())
206
                ->method($method)
207
                ->will($this->returnValue($returnValue));
208
        }
209
210
        return $mock;
211
    }
212
213
    /**
214
     * Return the value of private or protected property
215
     * @param class-string $class
0 ignored issues
show
Documentation Bug introduced by
The doc comment class-string at position 0 could not be parsed: Unknown type name 'class-string' at position 0 in class-string.
Loading history...
216
     * @param object $instance
217
     * @param string $name
218
     * @return mixed
219
     */
220
    public function getPropertyValue(string $class, object $instance, string $name)
221
    {
222
        $reflection = $this->getPrivateProtectedAttribute($class, $name);
223
        return $reflection->getValue($instance);
224
    }
225
226
    /**
227
     * Set the value of private or protected property
228
     * @param class-string $class
0 ignored issues
show
Documentation Bug introduced by
The doc comment class-string at position 0 could not be parsed: Unknown type name 'class-string' at position 0 in class-string.
Loading history...
229
     * @param object $instance
230
     * @param string $name
231
     * @param mixed $value
232
     * @return void
233
     */
234
    public function setPropertyValue(string $class, object $instance, string $name, $value)
235
    {
236
        $reflection = $this->getPrivateProtectedAttribute($class, $name);
237
        $reflection->setValue($instance, $value);
238
    }
239
}
240