| Code Coverage
| Classes and Traits | Functions and Methods | Lines
Total | 0.00% covered (danger) | 0.00% | 0 / 1 | 11.43% covered (danger) | 11.43% | 4 / 35 | CRAP | 27.17% covered (danger) | 27.17% | 50 / 184
Mockery | 0.00% covered (danger) | 0.00% | 0 / 1 | 13.89% covered (danger) | 13.89% | 5 / 36 | 2942.66 | 27.17% covered (danger) | 27.17% | 50 / 184
mock() | 100.00% covered (success) | 100.00% | 1 / 1 | 1 | 100.00% covered (success) | 100.00% | 2 / 2
instanceMock() | 0.00% covered (danger) | 0.00% | 0 / 1 | 2 | 0.00% covered (danger) | 0.00% | 0 / 2
namedMock() | 0.00% covered (danger) | 0.00% | 0 / 1 | 2 | 0.00% covered (danger) | 0.00% | 0 / 6
self() | 0.00% covered (danger) | 0.00% | 0 / 1 | 3.19 | 33.33% covered (danger) | 33.33% | 1 / 3
close() | 0.00% covered (danger) | 0.00% | 0 / 1 | 6 | 0.00% covered (danger) | 0.00% | 0 / 5
fetchMock($name) | 0.00% covered (danger) | 0.00% | 0 / 1 | 2 | 0.00% covered (danger) | 0.00% | 0 / 1
getContainer() | 0.00% covered (danger) | 0.00% | 0 / 1 | 2.15 | 66.67% covered (warning) | 66.67% | 2 / 3
setGenerator(Generator $generator) | 0.00% covered (danger) | 0.00% | 0 / 1 | 2 | 0.00% covered (danger) | 0.00% | 0 / 2
getGenerator() | 0.00% covered (danger) | 0.00% | 0 / 1 | 2.06 | 75.00% covered (warning) | 75.00% | 3 / 4
getDefaultGenerator() | 100.00% covered (success) | 100.00% | 1 / 1 | 1 | 100.00% covered (success) | 100.00% | 11 / 11
setLoader(Loader $loader) | 0.00% covered (danger) | 0.00% | 0 / 1 | 2 | 0.00% covered (danger) | 0.00% | 0 / 2
getLoader() | 0.00% covered (danger) | 0.00% | 0 / 1 | 2.06 | 75.00% covered (warning) | 75.00% | 3 / 4
getDefaultLoader() | 100.00% covered (success) | 100.00% | 1 / 1 | 1 | 100.00% covered (success) | 100.00% | 1 / 1
setContainer(Mockery\Container $container) | 0.00% covered (danger) | 0.00% | 0 / 1 | 1.12 | 50.00% covered (warning) | 50.00% | 1 / 2
resetContainer() | 0.00% covered (danger) | 0.00% | 0 / 1 | 2 | 0.00% covered (danger) | 0.00% | 0 / 2
any() | 0.00% covered (danger) | 0.00% | 0 / 1 | 2 | 0.00% covered (danger) | 0.00% | 0 / 2
type($expected) | 0.00% covered (danger) | 0.00% | 0 / 1 | 2 | 0.00% covered (danger) | 0.00% | 0 / 2
ducktype() | 0.00% covered (danger) | 0.00% | 0 / 1 | 2 | 0.00% covered (danger) | 0.00% | 0 / 2
subset(array $part) | 0.00% covered (danger) | 0.00% | 0 / 1 | 2 | 0.00% covered (danger) | 0.00% | 0 / 2
contains() | 0.00% covered (danger) | 0.00% | 0 / 1 | 2 | 0.00% covered (danger) | 0.00% | 0 / 2
hasKey($key) | 0.00% covered (danger) | 0.00% | 0 / 1 | 2 | 0.00% covered (danger) | 0.00% | 0 / 2
hasValue($val) | 0.00% covered (danger) | 0.00% | 0 / 1 | 2 | 0.00% covered (danger) | 0.00% | 0 / 2
on($closure) | 0.00% covered (danger) | 0.00% | 0 / 1 | 2 | 0.00% covered (danger) | 0.00% | 0 / 2
mustBe($expected) | 0.00% covered (danger) | 0.00% | 0 / 1 | 2 | 0.00% covered (danger) | 0.00% | 0 / 2
not($expected) | 0.00% covered (danger) | 0.00% | 0 / 1 | 2 | 0.00% covered (danger) | 0.00% | 0 / 2
anyOf() | 0.00% covered (danger) | 0.00% | 0 / 1 | 2 | 0.00% covered (danger) | 0.00% | 0 / 2
notAnyOf() | 0.00% covered (danger) | 0.00% | 0 / 1 | 2 | 0.00% covered (danger) | 0.00% | 0 / 2
getConfiguration() | 100.00% covered (success) | 100.00% | 1 / 1 | 2 | 100.00% covered (success) | 100.00% | 3 / 3
formatArgs($method, array $args = null) | 0.00% covered (danger) | 0.00% | 0 / 1 | 132 | 0.00% covered (danger) | 0.00% | 0 / 19
formatObjects(array $args = null) | 0.00% covered (danger) | 0.00% | 0 / 1 | 56 | 0.00% covered (danger) | 0.00% | 0 / 17
_objectToArray($object, $nesting = 3) | 0.00% covered (danger) | 0.00% | 0 / 1 | 110 | 0.00% covered (danger) | 0.00% | 0 / 20
_cleanupNesting($arg, $nesting) | 0.00% covered (danger) | 0.00% | 0 / 1 | 12 | 0.00% covered (danger) | 0.00% | 0 / 7
_cleanupArray($arg, $nesting = 3) | 0.00% covered (danger) | 0.00% | 0 / 1 | 30 | 0.00% covered (danger) | 0.00% | 0 / 9
parseShouldReturnArgs(\Mockery\MockInterface $mock, $args, $add) | 0.00% covered (danger) | 0.00% | 0 / 1 | 5.93 | 66.67% covered (warning) | 66.67% | 8 / 12
_buildDemeterChain(\Mockery\MockInterface $mock, $arg, $add) | 0.00% covered (danger) | 0.00% | 0 / 1 | 13.70 | 66.67% covered (warning) | 66.67% | 14 / 21
anonymous function ($n) use ($mock) | 100.00% covered (success) | 100.00% | 1 / 1 | 1 |  |  |

1 | <?php
2 | /**
3 | * Mockery
4 | *
5 | * LICENSE
6 | *
7 | * This source file is subject to the new BSD license that is bundled
8 | * with this package in the file LICENSE.txt.
9 | * It is also available through the world-wide-web at this URL:
10 | * http://github.com/padraic/mockery/blob/master/LICENSE
11 | * If you did not receive a copy of the license and are unable to
12 | * obtain it through the world-wide-web, please send an email
13 | * to padraic@php.net so we can send you a copy immediately.
14 | *
15 | * @category Mockery
16 | * @package Mockery
17 | * @copyright Copyright (c) 2010-2014 Pádraic Brady (http://blog.astrumfutura.com)
18 | * @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
19 | */
20 |
21 | use Mockery\Generator\MockConfigurationBuilder;
22 | use Mockery\Generator\CachingGenerator;
23 | use Mockery\Generator\StringManipulationGenerator;
24 | use Mockery\Generator\StringManipulation\Pass\CallTypeHintPass;
25 | use Mockery\Generator\StringManipulation\Pass\ClassNamePass;
26 | use Mockery\Generator\StringManipulation\Pass\ClassPass;
27 | use Mockery\Generator\StringManipulation\Pass\InstanceMockPass;
28 | use Mockery\Generator\StringManipulation\Pass\InterfacePass;
29 | use Mockery\Generator\StringManipulation\Pass\MethodDefinitionPass;
30 | use Mockery\Generator\StringManipulation\Pass\RemoveBuiltinMethodsThatAreFinalPass;
31 | use Mockery\Loader\EvalLoader;
32 | use Mockery\Loader\Loader;
33 |
34 | class Mockery
35 | {
36 | const BLOCKS = 'Mockery_Forward_Blocks';
37 |
38 | /**
39 | * Global container to hold all mocks for the current unit test running
40 | *
41 | * @var \Mockery\Container
42 | */
43 | protected static $_container = null;
44 |
45 | /**
46 | * Global configuration handler containing configuration options
47 | *
48 | * @var \Mockery\Configuration
49 | */
50 | protected static $_config = null;
51 |
52 | /**
53 | * @var \Mockery\Generator\Generator
54 | */
55 | protected static $_generator;
56 |
57 | /**
58 | * @var \Mockery\Loader\Loader
59 | */
60 | protected static $_loader;
61 |
62 | /**
63 | * Static shortcut to \Mockery\Container::mock()
64 | *
65 | * @return \Mockery\MockInterface
66 | */
67 | public static function mock()
68 | {
69 | $args = func_get_args();
70 | return call_user_func_array(array(self::getContainer(), 'mock'), $args);
71 | }
72 |
73 | public static function instanceMock()
74 | {
75 | $args = func_get_args();
76 | return call_user_func_array(array(self::getContainer(), 'mock'), $args);
77 | }
78 |
79 | /**
80 | * Static shortcut to \Mockery\Container::mock(), first argument names the
81 | * mock
82 | *
83 | * @return \Mockery\MockInterface
84 | */
85 | public static function namedMock()
86 | {
87 | $args = func_get_args();
88 | $name = array_shift($args);
89 | $builder = new MockConfigurationBuilder();
90 | $builder->setName($name);
91 | array_unshift($args, $builder);
92 | return call_user_func_array(array(self::getContainer(), 'mock'), $args);
93 | }
94 |
95 | /**
96 | * Static shortcut to \Mockery\Container::self()
97 | *
98 | * @return \Mockery\MockInterface
99 | */
100 | public static function self()
101 | {
102 | if (is_null(self::$_container)) {
103 | throw new \LogicException("You have not declared any mocks yet");
104 | }
105 |
106 | return self::$_container->self();
107 | }
108 |
109 | /**
110 | * Static shortcut to closing up and verifying all mocks in the global
111 | * container, and resetting the container static variable to null
112 | *
113 | * @return void
114 | */
115 | public static function close()
116 | {
117 | if (is_null(self::$_container)) return;
118 | self::$_container->mockery_teardown();
119 | self::$_container->mockery_close();
120 | self::$_container = null;
121 | }
122 |
123 | /**
124 | * Static fetching of a mock associated with a name or explicit class poser
125 | */
126 | public static function fetchMock($name)
127 | {
128 | return self::$_container->fetchMock($name);
129 | }
130 |
131 | /**
132 | * Get the container
133 | */
134 | public static function getContainer()
135 | {
136 | if (self::$_container) {
137 | return self::$_container;
138 | }
139 |
140 | return self::$_container = new Mockery\Container(self::getGenerator(), self::getLoader());
141 | }
142 |
143 | public static function setGenerator(Generator $generator)
144 | {
145 | self::$_generator = $generator;
146 | }
147 |
148 | public static function getGenerator()
149 | {
150 | if (self::$_generator) {
151 | return self::$_generator;
152 | }
153 |
154 | self::$_generator = self::getDefaultGenerator();
155 |
156 | return self::$_generator;
157 | }
158 |
159 | public static function getDefaultGenerator()
160 | {
161 | $generator = new StringManipulationGenerator(array(
162 | new CallTypeHintPass(),
163 | new ClassPass(),
164 | new ClassNamePass(),
165 | new InstanceMockPass(),
166 | new InterfacePass(),
167 | new MethodDefinitionPass(),
168 | new RemoveBuiltinMethodsThatAreFinalPass(),
169 | ));
170 |
171 | $generator = new CachingGenerator($generator);
172 |
173 | return $generator;
174 | }
175 |
176 | public static function setLoader(Loader $loader)
177 | {
178 | self::$_loader = $loader;
179 | }
180 |
181 | public static function getLoader()
182 | {
183 | if (self::$_loader) {
184 | return self::$_loader;
185 | }
186 |
187 | self::$_loader = self::getDefaultLoader();
188 |
189 | return self::$_loader;
190 | }
191 |
192 | public static function getDefaultLoader()
193 | {
194 | return new EvalLoader();
195 | }
196 |
197 |
198 | /**
199 | * Set the container
200 | */
201 | public static function setContainer(Mockery\Container $container)
202 | {
203 | return self::$_container = $container;
204 | }
205 |
206 | /**
207 | * Reset the container to null
208 | */
209 | public static function resetContainer()
210 | {
211 | self::$_container = null;
212 | }
213 |
214 | /**
215 | * Return instance of ANY matcher
216 | *
217 | * @return
218 | */
219 | public static function any()
220 | {
221 | $return = new \Mockery\Matcher\Any();
222 | return $return;
223 | }
224 |
225 | /**
226 | * Return instance of TYPE matcher
227 | *
228 | * @return
229 | */
230 | public static function type($expected)
231 | {
232 | $return = new \Mockery\Matcher\Type($expected);
233 | return $return;
234 | }
235 |
236 | /**
237 | * Return instance of DUCKTYPE matcher
238 | *
239 | * @return
240 | */
241 | public static function ducktype()
242 | {
243 | $return = new \Mockery\Matcher\Ducktype(func_get_args());
244 | return $return;
245 | }
246 |
247 | /**
248 | * Return instance of SUBSET matcher
249 | *
250 | * @return
251 | */
252 | public static function subset(array $part)
253 | {
254 | $return = new \Mockery\Matcher\Subset($part);
255 | return $return;
256 | }
257 |
258 | /**
259 | * Return instance of CONTAINS matcher
260 | *
261 | * @return
262 | */
263 | public static function contains()
264 | {
265 | $return = new \Mockery\Matcher\Contains(func_get_args());
266 | return $return;
267 | }
268 |
269 | /**
270 | * Return instance of HASKEY matcher
271 | *
272 | * @return
273 | */
274 | public static function hasKey($key)
275 | {
276 | $return = new \Mockery\Matcher\HasKey($key);
277 | return $return;
278 | }
279 |
280 | /**
281 | * Return instance of HASVALUE matcher
282 | *
283 | * @return
284 | */
285 | public static function hasValue($val)
286 | {
287 | $return = new \Mockery\Matcher\HasValue($val);
288 | return $return;
289 | }
290 |
291 | /**
292 | * Return instance of CLOSURE matcher
293 | *
294 | * @return
295 | */
296 | public static function on($closure)
297 | {
298 | $return = new \Mockery\Matcher\Closure($closure);
299 | return $return;
300 | }
301 |
302 | /**
303 | * Return instance of MUSTBE matcher
304 | *
305 | * @return
306 | */
307 | public static function mustBe($expected)
308 | {
309 | $return = new \Mockery\Matcher\MustBe($expected);
310 | return $return;
311 | }
312 |
313 | /**
314 | * Return instance of NOT matcher
315 | *
316 | * @return
317 | */
318 | public static function not($expected)
319 | {
320 | $return = new \Mockery\Matcher\Not($expected);
321 | return $return;
322 | }
323 |
324 | /**
325 | * Return instance of ANYOF matcher
326 | *
327 | * @return
328 | */
329 | public static function anyOf()
330 | {
331 | $return = new \Mockery\Matcher\AnyOf(func_get_args());
332 | return $return;
333 | }
334 |
335 | /**
336 | * Return instance of NOTANYOF matcher
337 | *
338 | * @return
339 | */
340 | public static function notAnyOf()
341 | {
342 | $return = new \Mockery\Matcher\NotAnyOf(func_get_args());
343 | return $return;
344 | }
345 |
346 | /**
347 | * Get the global configuration container
348 | */
349 | public static function getConfiguration()
350 | {
351 | if (is_null(self::$_config)) {
352 | self::$_config = new \Mockery\Configuration;
353 | }
354 | return self::$_config;
355 | }
356 |
357 | /**
358 | * Utility method to format method name and args into a string
359 | *
360 | * @param string $method
361 | * @param array $args
362 | * @return string
363 | */
364 | public static function formatArgs($method, array $args = null)
365 | {
366 | $return = $method . '(';
367 | if ($args && !empty($args)) {
368 | $parts = array();
369 | foreach($args as $arg) {
370 | if (is_object($arg)) {
371 | $parts[] = get_class($arg);
372 | } elseif (is_int($arg) || is_float($arg)) {
373 | $parts[] = $arg;
374 | } elseif (is_array($arg)) {
375 | $arg = preg_replace("{\s}", '', var_export($arg, true));
376 | $parts[] = (strlen($arg) > 1000) ? substr($arg, 0, 1000).'...)' : $arg;
377 | } elseif (is_bool($arg)) {
378 | $parts[] = $arg ? 'true' : 'false';
379 | } else {
380 | $parts[] = '"' . (string) $arg . '"';
381 | }
382 | }
383 | $return .= implode(', ', $parts); // TODO: improve format
384 |
385 | }
386 | $return .= ')';
387 | return $return;
388 | }
389 |
390 | /**
391 | * Utility function to format objects to printable arrays
392 | *
393 | * @param array $args
394 | * @return string
395 | */
396 | public static function formatObjects(array $args = null)
397 | {
398 | static $formatting;
399 | if($formatting)
400 | return '[Recursion]';
401 | $formatting = true;
402 | $hasObjects = false;
403 | $parts = array();
404 | $return = 'Objects: (';
405 | if ($args && !empty($args)) {
406 | foreach($args as $arg) {
407 | if (is_object($arg)) {
408 | $hasObjects = true;
409 | $parts[get_class($arg)] = self::_objectToArray($arg);
410 | }
411 | }
412 | }
413 | $return .= var_export($parts, true);
414 | $return .= ')';
415 | $return = $hasObjects ? $return : '';
416 | $formatting = false;
417 | return $return;
418 | }
419 |
420 | /**
421 | * Utility function to turn public properties
422 | * and public get* and is* method values into an array
423 | *
424 | * @param object $object
425 | * @return string
426 | */
427 | private static function _objectToArray($object, $nesting = 3)
428 | {
429 | if ($nesting == 0) {
430 | return array('...');
431 | }
432 | $reflection = new \ReflectionClass(get_class($object));
433 | $properties = array();
434 | foreach ($reflection->getProperties(\ReflectionProperty::IS_PUBLIC) as $publicProperty) {
435 | if ($publicProperty->isStatic()) continue;
436 | $name = $publicProperty->getName();
437 | $properties[$name] = self::_cleanupNesting($object->$name, $nesting);
438 | }
439 |
440 | $getters = array();
441 | foreach ($reflection->getMethods(\ReflectionProperty::IS_PUBLIC) as $publicMethod) {
442 | if ($publicMethod->isStatic()) continue;
443 | $name = $publicMethod->getName();
444 | $numberOfParameters = $publicMethod->getNumberOfParameters();
445 | if ((substr($name, 0, 3) === 'get' || substr($name, 0, 2) === 'is') && $numberOfParameters == 0) {
446 | try {
447 | $getters[$name] = self::_cleanupNesting($object->$name(), $nesting);
448 | } catch(\Exception $e) {
449 | $getters[$name] = '!! ' . get_class($e) . ': ' . $e->getMessage() . ' !!';
450 | }
451 | }
452 | }
453 | return array('class' => get_class($object), 'properties' => $properties, 'getters' => $getters);
454 | }
455 |
456 | private static function _cleanupNesting($arg, $nesting)
457 | {
458 | if (is_object($arg)) {
459 | $object = self::_objectToArray($arg, $nesting - 1);
460 | $object['class'] = get_class($arg);
461 | return $object;
462 | } elseif (is_array($arg)) {
463 | return self::_cleanupArray($arg, $nesting -1 );
464 | }
465 | return $arg;
466 | }
467 |
468 | private static function _cleanupArray($arg, $nesting = 3)
469 | {
470 | if ($nesting == 0) {
471 | return '...';
472 | }
473 | foreach ($arg as $key => $value) {
474 | if (is_array($value)) {
475 | $arg[$key] = self::_cleanupArray($value, $nesting -1);
476 | } elseif (is_object($value)) {
477 | $arg[$key] = self::_objectToArray($value, $nesting - 1);
478 | }
479 | }
480 | return $arg;
481 | }
482 |
483 | /**
484 | * Utility function to parse shouldReceive() arguments and generate
485 | * expectations from such as needed.
486 | *
487 | * @param \Mockery\MockInterface
488 | * @param array $args
489 | * @return \Mockery\CompositeExpectation
490 | */
491 | public static function parseShouldReturnArgs(\Mockery\MockInterface $mock, $args, $add)
492 | {
493 | $composite = new \Mockery\CompositeExpectation;
494 | foreach ($args as $arg) {
495 | if (is_array($arg)) {
496 | foreach($arg as $k=>$v) {
497 | $expectation = self::_buildDemeterChain($mock, $k, $add)->andReturn($v);
498 | $composite->add($expectation);
499 | }
500 | } elseif (is_string($arg)) {
501 | $expectation = self::_buildDemeterChain($mock, $arg, $add);
502 | $composite->add($expectation);
503 | }
504 | }
505 | return $composite;
506 | }
507 |
508 | /**
509 | * Sets up expectations on the members of the CompositeExpectation and
510 | * builds up any demeter chain that was passed to shouldReceive
511 | *
512 | * @param \Mockery\MockInterface $mock
513 | * @param string $arg
514 | * @param Closure $add
515 | * @return \Mockery\ExpectationDirector
516 | */
517 | protected static function _buildDemeterChain(\Mockery\MockInterface $mock, $arg, $add)
518 | {
519 | $container = $mock->mockery_getContainer();
520 | $names = explode('->', $arg);
521 | reset($names);
522 | if (!\Mockery::getConfiguration()->mockingNonExistentMethodsAllowed()
523 | && !$mock->mockery_isAnonymous()
524 | && !in_array(current($names), $mock->mockery_getMockableMethods())) {
525 | throw new \Mockery\Exception(
526 | 'Mockery\'s configuration currently forbids mocking the method '
527 | . current($names) . ' as it does not exist on the class or object '
528 | . 'being mocked'
529 | );
530 | }
531 | $exp = null;
532 | $nextExp = function ($n) use ($add) {return $add($n);};
533 | while (true) {
534 | $method = array_shift($names);
535 | $exp = $mock->mockery_getExpectationsFor($method);
536 | $needNew = false;
537 | if (is_null($exp) || empty($names)) {
538 | $needNew = true;
539 | }
540 | if ($needNew) $exp = $nextExp($method);
541 | if (empty($names)) break;
542 | if ($needNew) {
543 | $mock = $container->mock('demeter_' . $method);
544 | $exp->andReturn($mock);
545 | }
546 | $nextExp = function ($n) use ($mock) {return $mock->shouldReceive($n);};
547 | }
548 | return $exp;
549 | }
550 | }