Chris@14
|
1 <?php
|
Chris@14
|
2 /*
|
Chris@14
|
3 * This file is part of the phpunit-mock-objects package.
|
Chris@14
|
4 *
|
Chris@14
|
5 * (c) Sebastian Bergmann <sebastian@phpunit.de>
|
Chris@14
|
6 *
|
Chris@14
|
7 * For the full copyright and license information, please view the LICENSE
|
Chris@14
|
8 * file that was distributed with this source code.
|
Chris@14
|
9 */
|
Chris@14
|
10 namespace PHPUnit\Framework\MockObject\Builder;
|
Chris@14
|
11
|
Chris@14
|
12 use PHPUnit\Framework\Constraint\Constraint;
|
Chris@14
|
13 use PHPUnit\Framework\MockObject\Matcher;
|
Chris@14
|
14 use PHPUnit\Framework\MockObject\Matcher\Invocation;
|
Chris@14
|
15 use PHPUnit\Framework\MockObject\RuntimeException;
|
Chris@14
|
16 use PHPUnit\Framework\MockObject\Stub;
|
Chris@14
|
17 use PHPUnit\Framework\MockObject\Stub\MatcherCollection;
|
Chris@14
|
18
|
Chris@14
|
19 /**
|
Chris@14
|
20 * Builder for mocked or stubbed invocations.
|
Chris@14
|
21 *
|
Chris@14
|
22 * Provides methods for building expectations without having to resort to
|
Chris@14
|
23 * instantiating the various matchers manually. These methods also form a
|
Chris@14
|
24 * more natural way of reading the expectation. This class should be together
|
Chris@14
|
25 * with the test case PHPUnit\Framework\MockObject\TestCase.
|
Chris@14
|
26 */
|
Chris@14
|
27 class InvocationMocker implements MethodNameMatch
|
Chris@14
|
28 {
|
Chris@14
|
29 /**
|
Chris@14
|
30 * @var MatcherCollection
|
Chris@14
|
31 */
|
Chris@14
|
32 private $collection;
|
Chris@14
|
33
|
Chris@14
|
34 /**
|
Chris@14
|
35 * @var Matcher
|
Chris@14
|
36 */
|
Chris@14
|
37 private $matcher;
|
Chris@14
|
38
|
Chris@14
|
39 /**
|
Chris@14
|
40 * @var string[]
|
Chris@14
|
41 */
|
Chris@14
|
42 private $configurableMethods = [];
|
Chris@14
|
43
|
Chris@14
|
44 /**
|
Chris@14
|
45 * @param MatcherCollection $collection
|
Chris@14
|
46 * @param Invocation $invocationMatcher
|
Chris@14
|
47 * @param array $configurableMethods
|
Chris@14
|
48 */
|
Chris@14
|
49 public function __construct(MatcherCollection $collection, Invocation $invocationMatcher, array $configurableMethods)
|
Chris@14
|
50 {
|
Chris@14
|
51 $this->collection = $collection;
|
Chris@14
|
52 $this->matcher = new Matcher($invocationMatcher);
|
Chris@14
|
53
|
Chris@14
|
54 $this->collection->addMatcher($this->matcher);
|
Chris@14
|
55
|
Chris@14
|
56 $this->configurableMethods = $configurableMethods;
|
Chris@14
|
57 }
|
Chris@14
|
58
|
Chris@14
|
59 /**
|
Chris@14
|
60 * @return Matcher
|
Chris@14
|
61 */
|
Chris@14
|
62 public function getMatcher()
|
Chris@14
|
63 {
|
Chris@14
|
64 return $this->matcher;
|
Chris@14
|
65 }
|
Chris@14
|
66
|
Chris@14
|
67 /**
|
Chris@14
|
68 * @param mixed $id
|
Chris@14
|
69 *
|
Chris@14
|
70 * @return InvocationMocker
|
Chris@14
|
71 */
|
Chris@14
|
72 public function id($id)
|
Chris@14
|
73 {
|
Chris@14
|
74 $this->collection->registerId($id, $this);
|
Chris@14
|
75
|
Chris@14
|
76 return $this;
|
Chris@14
|
77 }
|
Chris@14
|
78
|
Chris@14
|
79 /**
|
Chris@14
|
80 * @param Stub $stub
|
Chris@14
|
81 *
|
Chris@14
|
82 * @return InvocationMocker
|
Chris@14
|
83 */
|
Chris@14
|
84 public function will(Stub $stub)
|
Chris@14
|
85 {
|
Chris@14
|
86 $this->matcher->setStub($stub);
|
Chris@14
|
87
|
Chris@14
|
88 return $this;
|
Chris@14
|
89 }
|
Chris@14
|
90
|
Chris@14
|
91 /**
|
Chris@14
|
92 * @param mixed $value
|
Chris@14
|
93 * @param mixed $nextValues, ...
|
Chris@14
|
94 *
|
Chris@14
|
95 * @return InvocationMocker
|
Chris@14
|
96 */
|
Chris@14
|
97 public function willReturn($value, ...$nextValues)
|
Chris@14
|
98 {
|
Chris@14
|
99 if (\count($nextValues) === 0) {
|
Chris@14
|
100 $stub = new Stub\ReturnStub($value);
|
Chris@14
|
101 } else {
|
Chris@14
|
102 $stub = new Stub\ConsecutiveCalls(
|
Chris@14
|
103 \array_merge([$value], $nextValues)
|
Chris@14
|
104 );
|
Chris@14
|
105 }
|
Chris@14
|
106
|
Chris@14
|
107 return $this->will($stub);
|
Chris@14
|
108 }
|
Chris@14
|
109
|
Chris@14
|
110 /**
|
Chris@14
|
111 * @param mixed $reference
|
Chris@14
|
112 *
|
Chris@14
|
113 * @return InvocationMocker
|
Chris@14
|
114 */
|
Chris@14
|
115 public function willReturnReference(&$reference)
|
Chris@14
|
116 {
|
Chris@14
|
117 $stub = new Stub\ReturnReference($reference);
|
Chris@14
|
118
|
Chris@14
|
119 return $this->will($stub);
|
Chris@14
|
120 }
|
Chris@14
|
121
|
Chris@14
|
122 /**
|
Chris@14
|
123 * @param array $valueMap
|
Chris@14
|
124 *
|
Chris@14
|
125 * @return InvocationMocker
|
Chris@14
|
126 */
|
Chris@14
|
127 public function willReturnMap(array $valueMap)
|
Chris@14
|
128 {
|
Chris@14
|
129 $stub = new Stub\ReturnValueMap($valueMap);
|
Chris@14
|
130
|
Chris@14
|
131 return $this->will($stub);
|
Chris@14
|
132 }
|
Chris@14
|
133
|
Chris@14
|
134 /**
|
Chris@14
|
135 * @param mixed $argumentIndex
|
Chris@14
|
136 *
|
Chris@14
|
137 * @return InvocationMocker
|
Chris@14
|
138 */
|
Chris@14
|
139 public function willReturnArgument($argumentIndex)
|
Chris@14
|
140 {
|
Chris@14
|
141 $stub = new Stub\ReturnArgument($argumentIndex);
|
Chris@14
|
142
|
Chris@14
|
143 return $this->will($stub);
|
Chris@14
|
144 }
|
Chris@14
|
145
|
Chris@14
|
146 /**
|
Chris@14
|
147 * @param callable $callback
|
Chris@14
|
148 *
|
Chris@14
|
149 * @return InvocationMocker
|
Chris@14
|
150 */
|
Chris@14
|
151 public function willReturnCallback($callback)
|
Chris@14
|
152 {
|
Chris@14
|
153 $stub = new Stub\ReturnCallback($callback);
|
Chris@14
|
154
|
Chris@14
|
155 return $this->will($stub);
|
Chris@14
|
156 }
|
Chris@14
|
157
|
Chris@14
|
158 /**
|
Chris@14
|
159 * @return InvocationMocker
|
Chris@14
|
160 */
|
Chris@14
|
161 public function willReturnSelf()
|
Chris@14
|
162 {
|
Chris@14
|
163 $stub = new Stub\ReturnSelf;
|
Chris@14
|
164
|
Chris@14
|
165 return $this->will($stub);
|
Chris@14
|
166 }
|
Chris@14
|
167
|
Chris@14
|
168 /**
|
Chris@14
|
169 * @param mixed $values, ...
|
Chris@14
|
170 *
|
Chris@14
|
171 * @return InvocationMocker
|
Chris@14
|
172 */
|
Chris@14
|
173 public function willReturnOnConsecutiveCalls(...$values)
|
Chris@14
|
174 {
|
Chris@14
|
175 $stub = new Stub\ConsecutiveCalls($values);
|
Chris@14
|
176
|
Chris@14
|
177 return $this->will($stub);
|
Chris@14
|
178 }
|
Chris@14
|
179
|
Chris@14
|
180 /**
|
Chris@14
|
181 * @param \Exception $exception
|
Chris@14
|
182 *
|
Chris@14
|
183 * @return InvocationMocker
|
Chris@14
|
184 */
|
Chris@14
|
185 public function willThrowException(\Exception $exception)
|
Chris@14
|
186 {
|
Chris@14
|
187 $stub = new Stub\Exception($exception);
|
Chris@14
|
188
|
Chris@14
|
189 return $this->will($stub);
|
Chris@14
|
190 }
|
Chris@14
|
191
|
Chris@14
|
192 /**
|
Chris@14
|
193 * @param mixed $id
|
Chris@14
|
194 *
|
Chris@14
|
195 * @return InvocationMocker
|
Chris@14
|
196 */
|
Chris@14
|
197 public function after($id)
|
Chris@14
|
198 {
|
Chris@14
|
199 $this->matcher->setAfterMatchBuilderId($id);
|
Chris@14
|
200
|
Chris@14
|
201 return $this;
|
Chris@14
|
202 }
|
Chris@14
|
203
|
Chris@14
|
204 /**
|
Chris@14
|
205 * @param array ...$arguments
|
Chris@14
|
206 *
|
Chris@14
|
207 * @return InvocationMocker
|
Chris@14
|
208 *
|
Chris@14
|
209 * @throws RuntimeException
|
Chris@14
|
210 */
|
Chris@14
|
211 public function with(...$arguments)
|
Chris@14
|
212 {
|
Chris@14
|
213 $this->canDefineParameters();
|
Chris@14
|
214
|
Chris@14
|
215 $this->matcher->setParametersMatcher(new Matcher\Parameters($arguments));
|
Chris@14
|
216
|
Chris@14
|
217 return $this;
|
Chris@14
|
218 }
|
Chris@14
|
219
|
Chris@14
|
220 /**
|
Chris@14
|
221 * @param array ...$arguments
|
Chris@14
|
222 *
|
Chris@14
|
223 * @return InvocationMocker
|
Chris@14
|
224 *
|
Chris@14
|
225 * @throws RuntimeException
|
Chris@14
|
226 */
|
Chris@14
|
227 public function withConsecutive(...$arguments)
|
Chris@14
|
228 {
|
Chris@14
|
229 $this->canDefineParameters();
|
Chris@14
|
230
|
Chris@14
|
231 $this->matcher->setParametersMatcher(new Matcher\ConsecutiveParameters($arguments));
|
Chris@14
|
232
|
Chris@14
|
233 return $this;
|
Chris@14
|
234 }
|
Chris@14
|
235
|
Chris@14
|
236 /**
|
Chris@14
|
237 * @return InvocationMocker
|
Chris@14
|
238 *
|
Chris@14
|
239 * @throws RuntimeException
|
Chris@14
|
240 */
|
Chris@14
|
241 public function withAnyParameters()
|
Chris@14
|
242 {
|
Chris@14
|
243 $this->canDefineParameters();
|
Chris@14
|
244
|
Chris@14
|
245 $this->matcher->setParametersMatcher(new Matcher\AnyParameters);
|
Chris@14
|
246
|
Chris@14
|
247 return $this;
|
Chris@14
|
248 }
|
Chris@14
|
249
|
Chris@14
|
250 /**
|
Chris@14
|
251 * @param Constraint|string $constraint
|
Chris@14
|
252 *
|
Chris@14
|
253 * @return InvocationMocker
|
Chris@14
|
254 *
|
Chris@14
|
255 * @throws RuntimeException
|
Chris@14
|
256 */
|
Chris@14
|
257 public function method($constraint)
|
Chris@14
|
258 {
|
Chris@14
|
259 if ($this->matcher->hasMethodNameMatcher()) {
|
Chris@14
|
260 throw new RuntimeException(
|
Chris@14
|
261 'Method name matcher is already defined, cannot redefine'
|
Chris@14
|
262 );
|
Chris@14
|
263 }
|
Chris@14
|
264
|
Chris@14
|
265 if (\is_string($constraint) && !\in_array(\strtolower($constraint), $this->configurableMethods)) {
|
Chris@14
|
266 throw new RuntimeException(
|
Chris@14
|
267 \sprintf(
|
Chris@14
|
268 'Trying to configure method "%s" which cannot be configured because it does not exist, has not been specified, is final, or is static',
|
Chris@14
|
269 $constraint
|
Chris@14
|
270 )
|
Chris@14
|
271 );
|
Chris@14
|
272 }
|
Chris@14
|
273
|
Chris@14
|
274 $this->matcher->setMethodNameMatcher(new Matcher\MethodName($constraint));
|
Chris@14
|
275
|
Chris@14
|
276 return $this;
|
Chris@14
|
277 }
|
Chris@14
|
278
|
Chris@14
|
279 /**
|
Chris@14
|
280 * Validate that a parameters matcher can be defined, throw exceptions otherwise.
|
Chris@14
|
281 *
|
Chris@14
|
282 * @throws RuntimeException
|
Chris@14
|
283 */
|
Chris@14
|
284 private function canDefineParameters()
|
Chris@14
|
285 {
|
Chris@14
|
286 if (!$this->matcher->hasMethodNameMatcher()) {
|
Chris@14
|
287 throw new RuntimeException(
|
Chris@14
|
288 'Method name matcher is not defined, cannot define parameter ' .
|
Chris@14
|
289 'matcher without one'
|
Chris@14
|
290 );
|
Chris@14
|
291 }
|
Chris@14
|
292
|
Chris@14
|
293 if ($this->matcher->hasParametersMatcher()) {
|
Chris@14
|
294 throw new RuntimeException(
|
Chris@14
|
295 'Parameter matcher is already defined, cannot redefine'
|
Chris@14
|
296 );
|
Chris@14
|
297 }
|
Chris@14
|
298 }
|
Chris@14
|
299 }
|