Subversion-Projekte lars-tiefland.laravel_shop

Revision

Zur aktuellen Revision | Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
148 lars 1
<?php declare(strict_types=1);
2
/*
3
 * This file is part of PHPUnit.
4
 *
5
 * (c) Sebastian Bergmann <sebastian@phpunit.de>
6
 *
7
 * For the full copyright and license information, please view the LICENSE
8
 * file that was distributed with this source code.
9
 */
10
namespace PHPUnit\Framework\MockObject\Builder;
11
 
12
use function array_map;
13
use function array_merge;
14
use function count;
15
use function in_array;
16
use function is_string;
17
use function strtolower;
18
use PHPUnit\Framework\Constraint\Constraint;
19
use PHPUnit\Framework\MockObject\ConfigurableMethod;
20
use PHPUnit\Framework\MockObject\IncompatibleReturnValueException;
21
use PHPUnit\Framework\MockObject\InvocationHandler;
22
use PHPUnit\Framework\MockObject\Matcher;
23
use PHPUnit\Framework\MockObject\MatcherAlreadyRegisteredException;
24
use PHPUnit\Framework\MockObject\MethodCannotBeConfiguredException;
25
use PHPUnit\Framework\MockObject\MethodNameAlreadyConfiguredException;
26
use PHPUnit\Framework\MockObject\MethodNameNotConfiguredException;
27
use PHPUnit\Framework\MockObject\MethodParametersAlreadyConfiguredException;
28
use PHPUnit\Framework\MockObject\Rule;
29
use PHPUnit\Framework\MockObject\Stub\ConsecutiveCalls;
30
use PHPUnit\Framework\MockObject\Stub\Exception;
31
use PHPUnit\Framework\MockObject\Stub\ReturnArgument;
32
use PHPUnit\Framework\MockObject\Stub\ReturnCallback;
33
use PHPUnit\Framework\MockObject\Stub\ReturnReference;
34
use PHPUnit\Framework\MockObject\Stub\ReturnSelf;
35
use PHPUnit\Framework\MockObject\Stub\ReturnStub;
36
use PHPUnit\Framework\MockObject\Stub\ReturnValueMap;
37
use PHPUnit\Framework\MockObject\Stub\Stub;
38
use Throwable;
39
 
40
/**
41
 * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
42
 */
43
final class InvocationMocker implements InvocationStubber, MethodNameMatch
44
{
45
    /**
46
     * @var InvocationHandler
47
     */
48
    private $invocationHandler;
49
 
50
    /**
51
     * @var Matcher
52
     */
53
    private $matcher;
54
 
55
    /**
56
     * @var ConfigurableMethod[]
57
     */
58
    private $configurableMethods;
59
 
60
    public function __construct(InvocationHandler $handler, Matcher $matcher, ConfigurableMethod ...$configurableMethods)
61
    {
62
        $this->invocationHandler   = $handler;
63
        $this->matcher             = $matcher;
64
        $this->configurableMethods = $configurableMethods;
65
    }
66
 
67
    /**
68
     * @throws MatcherAlreadyRegisteredException
69
     *
70
     * @return $this
71
     */
72
    public function id($id): self
73
    {
74
        $this->invocationHandler->registerMatcher($id, $this->matcher);
75
 
76
        return $this;
77
    }
78
 
79
    /**
80
     * @return $this
81
     */
82
    public function will(Stub $stub): Identity
83
    {
84
        $this->matcher->setStub($stub);
85
 
86
        return $this;
87
    }
88
 
89
    /**
90
     * @param mixed   $value
91
     * @param mixed[] $nextValues
92
     *
93
     * @throws IncompatibleReturnValueException
94
     */
95
    public function willReturn($value, ...$nextValues): self
96
    {
97
        if (count($nextValues) === 0) {
98
            $this->ensureTypeOfReturnValues([$value]);
99
 
100
            $stub = $value instanceof Stub ? $value : new ReturnStub($value);
101
        } else {
102
            $values = array_merge([$value], $nextValues);
103
 
104
            $this->ensureTypeOfReturnValues($values);
105
 
106
            $stub = new ConsecutiveCalls($values);
107
        }
108
 
109
        return $this->will($stub);
110
    }
111
 
112
    public function willReturnReference(&$reference): self
113
    {
114
        $stub = new ReturnReference($reference);
115
 
116
        return $this->will($stub);
117
    }
118
 
119
    public function willReturnMap(array $valueMap): self
120
    {
121
        $stub = new ReturnValueMap($valueMap);
122
 
123
        return $this->will($stub);
124
    }
125
 
126
    public function willReturnArgument($argumentIndex): self
127
    {
128
        $stub = new ReturnArgument($argumentIndex);
129
 
130
        return $this->will($stub);
131
    }
132
 
133
    public function willReturnCallback($callback): self
134
    {
135
        $stub = new ReturnCallback($callback);
136
 
137
        return $this->will($stub);
138
    }
139
 
140
    public function willReturnSelf(): self
141
    {
142
        $stub = new ReturnSelf;
143
 
144
        return $this->will($stub);
145
    }
146
 
147
    public function willReturnOnConsecutiveCalls(...$values): self
148
    {
149
        $stub = new ConsecutiveCalls($values);
150
 
151
        return $this->will($stub);
152
    }
153
 
154
    public function willThrowException(Throwable $exception): self
155
    {
156
        $stub = new Exception($exception);
157
 
158
        return $this->will($stub);
159
    }
160
 
161
    /**
162
     * @return $this
163
     */
164
    public function after($id): self
165
    {
166
        $this->matcher->setAfterMatchBuilderId($id);
167
 
168
        return $this;
169
    }
170
 
171
    /**
172
     * @param mixed[] $arguments
173
     *
174
     * @throws \PHPUnit\Framework\Exception
175
     * @throws MethodNameNotConfiguredException
176
     * @throws MethodParametersAlreadyConfiguredException
177
     *
178
     * @return $this
179
     */
180
    public function with(...$arguments): self
181
    {
182
        $this->ensureParametersCanBeConfigured();
183
 
184
        $this->matcher->setParametersRule(new Rule\Parameters($arguments));
185
 
186
        return $this;
187
    }
188
 
189
    /**
190
     * @param array ...$arguments
191
     *
192
     * @throws \PHPUnit\Framework\Exception
193
     * @throws MethodNameNotConfiguredException
194
     * @throws MethodParametersAlreadyConfiguredException
195
     *
196
     * @return $this
197
     */
198
    public function withConsecutive(...$arguments): self
199
    {
200
        $this->ensureParametersCanBeConfigured();
201
 
202
        $this->matcher->setParametersRule(new Rule\ConsecutiveParameters($arguments));
203
 
204
        return $this;
205
    }
206
 
207
    /**
208
     * @throws MethodNameNotConfiguredException
209
     * @throws MethodParametersAlreadyConfiguredException
210
     *
211
     * @return $this
212
     */
213
    public function withAnyParameters(): self
214
    {
215
        $this->ensureParametersCanBeConfigured();
216
 
217
        $this->matcher->setParametersRule(new Rule\AnyParameters);
218
 
219
        return $this;
220
    }
221
 
222
    /**
223
     * @param Constraint|string $constraint
224
     *
225
     * @throws \PHPUnit\Framework\InvalidArgumentException
226
     * @throws MethodCannotBeConfiguredException
227
     * @throws MethodNameAlreadyConfiguredException
228
     *
229
     * @return $this
230
     */
231
    public function method($constraint): self
232
    {
233
        if ($this->matcher->hasMethodNameRule()) {
234
            throw new MethodNameAlreadyConfiguredException;
235
        }
236
 
237
        $configurableMethodNames = array_map(
238
            static function (ConfigurableMethod $configurable)
239
            {
240
                return strtolower($configurable->getName());
241
            },
242
            $this->configurableMethods
243
        );
244
 
245
        if (is_string($constraint) && !in_array(strtolower($constraint), $configurableMethodNames, true)) {
246
            throw new MethodCannotBeConfiguredException($constraint);
247
        }
248
 
249
        $this->matcher->setMethodNameRule(new Rule\MethodName($constraint));
250
 
251
        return $this;
252
    }
253
 
254
    /**
255
     * @throws MethodNameNotConfiguredException
256
     * @throws MethodParametersAlreadyConfiguredException
257
     */
258
    private function ensureParametersCanBeConfigured(): void
259
    {
260
        if (!$this->matcher->hasMethodNameRule()) {
261
            throw new MethodNameNotConfiguredException;
262
        }
263
 
264
        if ($this->matcher->hasParametersRule()) {
265
            throw new MethodParametersAlreadyConfiguredException;
266
        }
267
    }
268
 
269
    private function getConfiguredMethod(): ?ConfigurableMethod
270
    {
271
        $configuredMethod = null;
272
 
273
        foreach ($this->configurableMethods as $configurableMethod) {
274
            if ($this->matcher->getMethodNameRule()->matchesName($configurableMethod->getName())) {
275
                if ($configuredMethod !== null) {
276
                    return null;
277
                }
278
 
279
                $configuredMethod = $configurableMethod;
280
            }
281
        }
282
 
283
        return $configuredMethod;
284
    }
285
 
286
    /**
287
     * @throws IncompatibleReturnValueException
288
     */
289
    private function ensureTypeOfReturnValues(array $values): void
290
    {
291
        $configuredMethod = $this->getConfiguredMethod();
292
 
293
        if ($configuredMethod === null) {
294
            return;
295
        }
296
 
297
        foreach ($values as $value) {
298
            if (!$configuredMethod->mayReturn($value)) {
299
                throw new IncompatibleReturnValueException(
300
                    $configuredMethod,
301
                    $value
302
                );
303
            }
304
        }
305
    }
306
}