Completed
Pull Request — master (#266)
by Marco
04:32
created

NullObjectFunctionalTest::assertNullMethodCall()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 11
Code Lines 5

Duplication

Lines 0
Ratio 0 %
Metric Value
dl 0
loc 11
rs 9.4286
cc 1
eloc 5
nc 1
nop 3
1
<?php
2
/*
3
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
4
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
5
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
6
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
7
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
8
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
9
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
10
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
11
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
12
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
13
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
14
 *
15
 * This software consists of voluntary contributions made by many individuals
16
 * and is licensed under the MIT license.
17
 */
18
19
namespace ProxyManagerTest\Functional;
20
21
use PHPUnit_Framework_TestCase;
22
use ProxyManager\Generator\ClassGenerator;
23
use ProxyManager\Generator\Util\UniqueIdentifierGenerator;
24
use ProxyManager\GeneratorStrategy\EvaluatingGeneratorStrategy;
25
use ProxyManager\Proxy\NullObjectInterface;
26
use ProxyManager\ProxyGenerator\NullObjectGenerator;
27
use ProxyManagerTestAsset\BaseClass;
28
use ProxyManagerTestAsset\BaseInterface;
29
use ProxyManagerTestAsset\ClassWithMethodWithByRefVariadicFunction;
30
use ProxyManagerTestAsset\ClassWithMethodWithVariadicFunction;
31
use ProxyManagerTestAsset\ClassWithSelfHint;
32
use ReflectionClass;
33
34
/**
35
 * Tests for {@see \ProxyManager\ProxyGenerator\NullObjectGenerator} produced objects
36
 *
37
 * @author Vincent Blanchon <[email protected]>
38
 * @license MIT
39
 *
40
 * @group Functional
41
 * @coversNothing
42
 */
43
class NullObjectFunctionalTest extends PHPUnit_Framework_TestCase
44
{
45
    /**
46
     * @dataProvider getProxyMethods
47
     *
48
     * @param string  $className
49
     * @param string  $method
50
     * @param mixed[] $params
51
     */
52
    public function testMethodCalls($className, $method, $params)
53
    {
54
        $proxyName = $this->generateProxy($className);
55
56
        /* @var $proxy NullObjectInterface */
57
        $proxy = $proxyName::staticProxyConstructor();
58
59
        $this->assertNullMethodCall($proxy, $method, $params);
60
    }
61
62
    /**
63
     * @dataProvider getProxyMethods
64
     *
65
     * @param string  $className
66
     * @param string  $method
67
     * @param mixed[] $params
68
     */
69
    public function testMethodCallsAfterUnSerialization($className, $method, $params)
70
    {
71
        $proxyName = $this->generateProxy($className);
72
        /* @var $proxy NullObjectInterface */
73
        $proxy     = unserialize(serialize($proxyName::staticProxyConstructor()));
74
75
        $this->assertNullMethodCall($proxy, $method, $params);
76
    }
77
78
    /**
79
     * @dataProvider getProxyMethods
80
     *
81
     * @param string  $className
82
     * @param string  $method
83
     * @param mixed[] $params
84
     */
85
    public function testMethodCallsAfterCloning($className, $method, $params)
86
    {
87
        $proxyName = $this->generateProxy($className);
88
89
        /* @var $proxy NullObjectInterface */
90
        $proxy     = $proxyName::staticProxyConstructor();
91
92
        $this->assertNullMethodCall(clone $proxy, $method, $params);
93
    }
94
95
    /**
96
     * @dataProvider getPropertyAccessProxies
97
     *
98
     * @param NullObjectInterface $proxy
99
     * @param string              $publicProperty
100
     */
101
    public function testPropertyReadAccess(NullObjectInterface $proxy, $publicProperty)
102
    {
103
        $this->assertSame(null, $proxy->$publicProperty);
104
    }
105
106
    /**
107
     * @dataProvider getPropertyAccessProxies
108
     *
109
     * @param NullObjectInterface $proxy
110
     * @param string              $publicProperty
111
     */
112
    public function testPropertyWriteAccess(NullObjectInterface $proxy, $publicProperty)
113
    {
114
        $newValue               = uniqid();
115
        $proxy->$publicProperty = $newValue;
116
117
        $this->assertSame($newValue, $proxy->$publicProperty);
118
    }
119
120
    /**
121
     * @dataProvider getPropertyAccessProxies
122
     *
123
     * @param NullObjectInterface $proxy
124
     * @param string              $publicProperty
125
     */
126
    public function testPropertyExistence(NullObjectInterface $proxy, $publicProperty)
127
    {
128
        $this->assertSame(null, $proxy->$publicProperty);
129
    }
130
131
    /**
132
     * @dataProvider getPropertyAccessProxies
133
     *
134
     * @param NullObjectInterface $proxy
135
     * @param string              $publicProperty
136
     */
137
    public function testPropertyUnset(NullObjectInterface $proxy, $publicProperty)
138
    {
139
        unset($proxy->$publicProperty);
140
141
        $this->assertFalse(isset($proxy->$publicProperty));
142
    }
143
144
    /**
145
     * Generates a proxy for the given class name, and retrieves its class name
146
     *
147
     * @param string $parentClassName
148
     *
149
     * @return string
150
     */
151
    private function generateProxy($parentClassName)
152
    {
153
        $generatedClassName = __NAMESPACE__ . '\\' . UniqueIdentifierGenerator::getIdentifier('Foo');
154
        $generator          = new NullObjectGenerator();
155
        $generatedClass     = new ClassGenerator($generatedClassName);
156
        $strategy           = new EvaluatingGeneratorStrategy();
157
158
        $generator->generate(new ReflectionClass($parentClassName), $generatedClass);
159
        $strategy->generate($generatedClass);
160
161
        return $generatedClassName;
162
    }
163
164
    /**
165
     * Generates a list of object | invoked method | parameters | expected result
166
     *
167
     * @return array
168
     */
169
    public function getProxyMethods()
170
    {
171
        $selfHintParam = new ClassWithSelfHint();
172
173
        return [
174
            [
175
                BaseClass::class,
176
                'publicMethod',
177
                [],
178
                'publicMethodDefault'
179
            ],
180
            [
181
                BaseClass::class,
182
                'publicTypeHintedMethod',
183
                ['param' => new \stdClass()],
184
                'publicTypeHintedMethodDefault'
185
            ],
186
            [
187
                BaseClass::class,
188
                'publicByReferenceMethod',
189
                [],
190
                'publicByReferenceMethodDefault'
191
            ],
192
            [
193
                BaseInterface::class,
194
                'publicMethod',
195
                [],
196
                'publicMethodDefault'
197
            ],
198
            [
199
                ClassWithSelfHint::class,
200
                'selfHintMethod',
201
                ['parameter' => $selfHintParam],
202
                $selfHintParam
203
            ],
204
            [
205
                ClassWithMethodWithVariadicFunction::class,
206
                'buz',
207
                ['Ocramius', 'Malukenho'],
208
                null
209
            ],
210
            [
211
                ClassWithMethodWithByRefVariadicFunction::class,
212
                'tuz',
213
                ['Ocramius', 'Malukenho'],
214
                null
215
            ],
216
        ];
217
    }
218
219
    /**
220
     * Generates proxies and instances with a public property to feed to the property accessor methods
221
     *
222
     * @return array
223
     */
224
    public function getPropertyAccessProxies()
225
    {
226
        $proxyName1 = $this->generateProxy(BaseClass::class);
227
        $proxyName2 = $this->generateProxy(BaseClass::class);
228
229
        return [
230
            [
231
                $proxyName1::staticProxyConstructor(),
232
                'publicProperty',
233
                'publicPropertyDefault',
234
            ],
235
            [
236
                unserialize(serialize($proxyName2::staticProxyConstructor())),
237
                'publicProperty',
238
                'publicPropertyDefault',
239
            ],
240
        ];
241
    }
242
243
    /**
244
     * @param NullObjectInterface $proxy
245
     * @param string              $methodName
246
     * @param array               $parameters
247
     */
248
    private function assertNullMethodCall(NullObjectInterface $proxy, $methodName, array $parameters)
249
    {
250
        /* @var callable $method */
251
        $method = [$proxy, $methodName];
252
253
        self::assertInternalType('callable', $method);
254
255
        $parameterValues = array_values($parameters);
256
257
        self::assertSame(null, $method(...$parameterValues));
258
    }
259
}
260