| [ Index ] |
PHP Cross Reference of Moodle 1.9.3 [Build 15-Oct-2008] |
[Summary view] [Print] [Text view]
1 <?php 2 /** 3 * base include file for SimpleTest 4 * @package SimpleTest 5 * @subpackage MockObjects 6 * @version $Id$ 7 */ 8 9 /**#@+ 10 * include SimpleTest files 11 */ 12 require_once(dirname(__FILE__) . '/expectation.php'); 13 require_once(dirname(__FILE__) . '/simpletest.php'); 14 require_once(dirname(__FILE__) . '/dumper.php'); 15 if (version_compare(phpversion(), '5') >= 0) { 16 require_once(dirname(__FILE__) . '/reflection_php5.php'); 17 } else { 18 require_once(dirname(__FILE__) . '/reflection_php4.php'); 19 } 20 /**#@-*/ 21 22 /** 23 * Default character simpletest will substitute for any value 24 */ 25 if (! defined('MOCK_ANYTHING')) { 26 define('MOCK_ANYTHING', '*'); 27 } 28 29 /** 30 * Parameter comparison assertion. 31 * @package SimpleTest 32 * @subpackage MockObjects 33 */ 34 class ParametersExpectation extends SimpleExpectation { 35 var $_expected; 36 37 /** 38 * Sets the expected parameter list. 39 * @param array $parameters Array of parameters including 40 * those that are wildcarded. 41 * If the value is not an array 42 * then it is considered to match any. 43 * @param string $message Customised message on failure. 44 * @access public 45 */ 46 function ParametersExpectation($expected = false, $message = '%s') { 47 $this->SimpleExpectation($message); 48 $this->_expected = $expected; 49 } 50 51 /** 52 * Tests the assertion. True if correct. 53 * @param array $parameters Comparison values. 54 * @return boolean True if correct. 55 * @access public 56 */ 57 function test($parameters) { 58 if (! is_array($this->_expected)) { 59 return true; 60 } 61 if (count($this->_expected) != count($parameters)) { 62 return false; 63 } 64 for ($i = 0; $i < count($this->_expected); $i++) { 65 if (! $this->_testParameter($parameters[$i], $this->_expected[$i])) { 66 return false; 67 } 68 } 69 return true; 70 } 71 72 /** 73 * Tests an individual parameter. 74 * @param mixed $parameter Value to test. 75 * @param mixed $expected Comparison value. 76 * @return boolean True if expectation 77 * fulfilled. 78 * @access private 79 */ 80 function _testParameter($parameter, $expected) { 81 $comparison = $this->_coerceToExpectation($expected); 82 return $comparison->test($parameter); 83 } 84 85 /** 86 * Returns a human readable test message. 87 * @param array $comparison Incoming parameter list. 88 * @return string Description of success 89 * or failure. 90 * @access public 91 */ 92 function testMessage($parameters) { 93 if ($this->test($parameters)) { 94 return "Expectation of " . count($this->_expected) . 95 " arguments of [" . $this->_renderArguments($this->_expected) . 96 "] is correct"; 97 } else { 98 return $this->_describeDifference($this->_expected, $parameters); 99 } 100 } 101 102 /** 103 * Message to display if expectation differs from 104 * the parameters actually received. 105 * @param array $expected Expected parameters as list. 106 * @param array $parameters Actual parameters received. 107 * @return string Description of difference. 108 * @access private 109 */ 110 function _describeDifference($expected, $parameters) { 111 if (count($expected) != count($parameters)) { 112 return "Expected " . count($expected) . 113 " arguments of [" . $this->_renderArguments($expected) . 114 "] but got " . count($parameters) . 115 " arguments of [" . $this->_renderArguments($parameters) . "]"; 116 } 117 $messages = array(); 118 for ($i = 0; $i < count($expected); $i++) { 119 $comparison = $this->_coerceToExpectation($expected[$i]); 120 if (! $comparison->test($parameters[$i])) { 121 $messages[] = "parameter " . ($i + 1) . " with [" . 122 $comparison->overlayMessage($parameters[$i], $this->_getDumper()) . "]"; 123 } 124 } 125 return "Parameter expectation differs at " . implode(" and ", $messages); 126 } 127 128 /** 129 * Creates an identical expectation if the 130 * object/value is not already some type 131 * of expectation. 132 * @param mixed $expected Expected value. 133 * @return SimpleExpectation Expectation object. 134 * @access private 135 */ 136 function _coerceToExpectation($expected) { 137 if (SimpleExpectation::isExpectation($expected)) { 138 return $expected; 139 } 140 return new IdenticalExpectation($expected); 141 } 142 143 /** 144 * Renders the argument list as a string for 145 * messages. 146 * @param array $args Incoming arguments. 147 * @return string Simple description of type and value. 148 * @access private 149 */ 150 function _renderArguments($args) { 151 $descriptions = array(); 152 if (is_array($args)) { 153 foreach ($args as $arg) { 154 $dumper = &new SimpleDumper(); 155 $descriptions[] = $dumper->describeValue($arg); 156 } 157 } 158 return implode(', ', $descriptions); 159 } 160 } 161 162 /** 163 * Confirms that the number of calls on a method is as expected. 164 */ 165 class CallCountExpectation extends SimpleExpectation { 166 var $_method; 167 var $_count; 168 169 /** 170 * Stashes the method and expected count for later 171 * reporting. 172 * @param string $method Name of method to confirm against. 173 * @param integer $count Expected number of calls. 174 * @param string $message Custom error message. 175 */ 176 function CallCountExpectation($method, $count, $message = '%s') { 177 $this->_method = $method; 178 $this->_count = $count; 179 $this->SimpleExpectation($message); 180 } 181 182 /** 183 * Tests the assertion. True if correct. 184 * @param integer $compare Measured call count. 185 * @return boolean True if expected. 186 * @access public 187 */ 188 function test($compare) { 189 return ($this->_count == $compare); 190 } 191 192 /** 193 * Reports the comparison. 194 * @param integer $compare Measured call count. 195 * @return string Message to show. 196 * @access public 197 */ 198 function testMessage($compare) { 199 return 'Expected call count for [' . $this->_method . 200 '] was [' . $this->_count . 201 '] got [' . $compare . ']'; 202 } 203 } 204 205 /** 206 * Confirms that the number of calls on a method is as expected. 207 */ 208 class MinimumCallCountExpectation extends SimpleExpectation { 209 var $_method; 210 var $_count; 211 212 /** 213 * Stashes the method and expected count for later 214 * reporting. 215 * @param string $method Name of method to confirm against. 216 * @param integer $count Minimum number of calls. 217 * @param string $message Custom error message. 218 */ 219 function MinimumCallCountExpectation($method, $count, $message = '%s') { 220 $this->_method = $method; 221 $this->_count = $count; 222 $this->SimpleExpectation($message); 223 } 224 225 /** 226 * Tests the assertion. True if correct. 227 * @param integer $compare Measured call count. 228 * @return boolean True if enough. 229 * @access public 230 */ 231 function test($compare) { 232 return ($this->_count <= $compare); 233 } 234 235 /** 236 * Reports the comparison. 237 * @param integer $compare Measured call count. 238 * @return string Message to show. 239 * @access public 240 */ 241 function testMessage($compare) { 242 return 'Minimum call count for [' . $this->_method . 243 '] was [' . $this->_count . 244 '] got [' . $compare . ']'; 245 } 246 } 247 248 /** 249 * Confirms that the number of calls on a method is as expected. 250 */ 251 class MaximumCallCountExpectation extends SimpleExpectation { 252 var $_method; 253 var $_count; 254 255 /** 256 * Stashes the method and expected count for later 257 * reporting. 258 * @param string $method Name of method to confirm against. 259 * @param integer $count Minimum number of calls. 260 * @param string $message Custom error message. 261 */ 262 function MaximumCallCountExpectation($method, $count, $message = '%s') { 263 $this->_method = $method; 264 $this->_count = $count; 265 $this->SimpleExpectation($message); 266 } 267 268 /** 269 * Tests the assertion. True if correct. 270 * @param integer $compare Measured call count. 271 * @return boolean True if not over. 272 * @access public 273 */ 274 function test($compare) { 275 return ($this->_count >= $compare); 276 } 277 278 /** 279 * Reports the comparison. 280 * @param integer $compare Measured call count. 281 * @return string Message to show. 282 * @access public 283 */ 284 function testMessage($compare) { 285 return 'Maximum call count for [' . $this->_method . 286 '] was [' . $this->_count . 287 '] got [' . $compare . ']'; 288 } 289 } 290 291 /** 292 * Retrieves values and references by searching the 293 * parameter lists until a match is found. 294 * @package SimpleTest 295 * @subpackage MockObjects 296 */ 297 class CallMap { 298 var $_map; 299 300 /** 301 * Creates an empty call map. 302 * @access public 303 */ 304 function CallMap() { 305 $this->_map = array(); 306 } 307 308 /** 309 * Stashes a value against a method call. 310 * @param array $parameters Arguments including wildcards. 311 * @param mixed $value Value copied into the map. 312 * @access public 313 */ 314 function addValue($parameters, $value) { 315 $this->addReference($parameters, $value); 316 } 317 318 /** 319 * Stashes a reference against a method call. 320 * @param array $parameters Array of arguments (including wildcards). 321 * @param mixed $reference Array reference placed in the map. 322 * @access public 323 */ 324 function addReference($parameters, &$reference) { 325 $place = count($this->_map); 326 $this->_map[$place] = array(); 327 $this->_map[$place]["params"] = new ParametersExpectation($parameters); 328 $this->_map[$place]["content"] = &$reference; 329 } 330 331 /** 332 * Searches the call list for a matching parameter 333 * set. Returned by reference. 334 * @param array $parameters Parameters to search by 335 * without wildcards. 336 * @return object Object held in the first matching 337 * slot, otherwise null. 338 * @access public 339 */ 340 function &findFirstMatch($parameters) { 341 $slot = $this->_findFirstSlot($parameters); 342 if (!isset($slot)) { 343 $null = null; 344 return $null; 345 } 346 return $slot["content"]; 347 } 348 349 /** 350 * Searches the call list for a matching parameter 351 * set. True if successful. 352 * @param array $parameters Parameters to search by 353 * without wildcards. 354 * @return boolean True if a match is present. 355 * @access public 356 */ 357 function isMatch($parameters) { 358 return ($this->_findFirstSlot($parameters) != null); 359 } 360 361 /** 362 * Searches the map for a matching item. 363 * @param array $parameters Parameters to search by 364 * without wildcards. 365 * @return array Reference to slot or null. 366 * @access private 367 */ 368 function &_findFirstSlot($parameters) { 369 $count = count($this->_map); 370 for ($i = 0; $i < $count; $i++) { 371 if ($this->_map[$i]["params"]->test($parameters)) { 372 return $this->_map[$i]; 373 } 374 } 375 $null = null; 376 return $null; 377 } 378 } 379 380 /** 381 * An empty collection of methods that can have their 382 * return values set and expectations made of the 383 * calls upon them. The mock will assert the 384 * expectations against it's attached test case in 385 * addition to the server stub behaviour. 386 * @package SimpleTest 387 * @subpackage MockObjects 388 */ 389 class SimpleMock { 390 var $_wildcard = MOCK_ANYTHING; 391 var $_is_strict = true; 392 var $_returns; 393 var $_return_sequence; 394 var $_call_counts; 395 var $_expected_counts; 396 var $_max_counts; 397 var $_expected_args; 398 var $_expected_args_at; 399 400 /** 401 * Creates an empty return list and expectation list. 402 * All call counts are set to zero. 403 * @param SimpleTestCase $test Test case to test expectations in. 404 * @param mixed $wildcard Parameter matching wildcard. 405 * @param boolean $is_strict Enables method name checks on 406 * expectations. 407 */ 408 function SimpleMock() { 409 $this->_returns = array(); 410 $this->_return_sequence = array(); 411 $this->_call_counts = array(); 412 $test = &$this->_getCurrentTestCase(); 413 $test->tell($this); 414 $this->_expected_counts = array(); 415 $this->_max_counts = array(); 416 $this->_expected_args = array(); 417 $this->_expected_args_at = array(); 418 } 419 420 /** 421 * Disables a name check when setting expectations. 422 * This hack is needed for the partial mocks. 423 * @access public 424 */ 425 function disableExpectationNameChecks() { 426 $this->_is_strict = false; 427 } 428 429 /** 430 * Changes the default wildcard object. 431 * @param mixed $wildcard Parameter matching wildcard. 432 * @access public 433 */ 434 function setWildcard($wildcard) { 435 $this->_wildcard = $wildcard; 436 } 437 438 /** 439 * Finds currently running test. 440 * @return SimpeTestCase Current test case. 441 * @access protected 442 */ 443 function &_getCurrentTestCase() { 444 $context = &SimpleTest::getContext(); 445 return $context->getTest(); 446 } 447 448 /** 449 * Die if bad arguments array is passed 450 * @param mixed $args The arguments value to be checked. 451 * @param string $task Description of task attempt. 452 * @return boolean Valid arguments 453 * @access private 454 */ 455 function _checkArgumentsIsArray($args, $task) { 456 if (! is_array($args)) { 457 trigger_error( 458 "Cannot $task as \$args parameter is not an array", 459 E_USER_ERROR); 460 } 461 } 462 463 /** 464 * Triggers a PHP error if the method is not part 465 * of this object. 466 * @param string $method Name of method. 467 * @param string $task Description of task attempt. 468 * @access protected 469 */ 470 function _dieOnNoMethod($method, $task) { 471 if ($this->_is_strict && ! method_exists($this, $method)) { 472 trigger_error( 473 "Cannot $task as no $method}() in class " . get_class($this), 474 E_USER_ERROR); 475 } 476 } 477 478 /** 479 * Replaces wildcard matches with wildcard 480 * expectations in the argument list. 481 * @param array $args Raw argument list. 482 * @return array Argument list with 483 * expectations. 484 * @access private 485 */ 486 function _replaceWildcards($args) { 487 if ($args === false) { 488 return false; 489 } 490 for ($i = 0; $i < count($args); $i++) { 491 if ($args[$i] === $this->_wildcard) { 492 $args[$i] = new AnythingExpectation(); 493 } 494 } 495 return $args; 496 } 497 498 /** 499 * Adds one to the call count of a method. 500 * @param string $method Method called. 501 * @param array $args Arguments as an array. 502 * @access protected 503 */ 504 function _addCall($method, $args) { 505 if (!isset($this->_call_counts[$method])) { 506 $this->_call_counts[$method] = 0; 507 } 508 $this->_call_counts[$method]++; 509 } 510 511 /** 512 * Fetches the call count of a method so far. 513 * @param string $method Method name called. 514 * @return Number of calls so far. 515 * @access public 516 */ 517 function getCallCount($method) { 518 $this->_dieOnNoMethod($method, "get call count"); 519 $method = strtolower($method); 520 if (! isset($this->_call_counts[$method])) { 521 return 0; 522 } 523 return $this->_call_counts[$method]; 524 } 525 526 /** 527 * Sets a return for a parameter list that will 528 * be passed by value for all calls to this method. 529 * @param string $method Method name. 530 * @param mixed $value Result of call passed by value. 531 * @param array $args List of parameters to match 532 * including wildcards. 533 * @access public 534 */ 535 function setReturnValue($method, $value, $args = false) { 536 $this->_dieOnNoMethod($method, "set return value"); 537 $args = $this->_replaceWildcards($args); 538 $method = strtolower($method); 539 if (! isset($this->_returns[$method])) { 540 $this->_returns[$method] = new CallMap(); 541 } 542 $this->_returns[$method]->addValue($args, $value); 543 } 544 545 /** 546 * Sets a return for a parameter list that will 547 * be passed by value only when the required call count 548 * is reached. 549 * @param integer $timing Number of calls in the future 550 * to which the result applies. If 551 * not set then all calls will return 552 * the value. 553 * @param string $method Method name. 554 * @param mixed $value Result of call passed by value. 555 * @param array $args List of parameters to match 556 * including wildcards. 557 * @access public 558 */ 559 function setReturnValueAt($timing, $method, $value, $args = false) { 560 $this->_dieOnNoMethod($method, "set return value sequence"); 561 $args = $this->_replaceWildcards($args); 562 $method = strtolower($method); 563 if (! isset($this->_return_sequence[$method])) { 564 $this->_return_sequence[$method] = array(); 565 } 566 if (! isset($this->_return_sequence[$method][$timing])) { 567 $this->_return_sequence[$method][$timing] = new CallMap(); 568 } 569 $this->_return_sequence[$method][$timing]->addValue($args, $value); 570 } 571 572 /** 573 * Sets a return for a parameter list that will 574 * be passed by reference for all calls. 575 * @param string $method Method name. 576 * @param mixed $reference Result of the call will be this object. 577 * @param array $args List of parameters to match 578 * including wildcards. 579 * @access public 580 */ 581 function setReturnReference($method, &$reference, $args = false) { 582 $this->_dieOnNoMethod($method, "set return reference"); 583 $args = $this->_replaceWildcards($args); 584 $method = strtolower($method); 585 if (! isset($this->_returns[$method])) { 586 $this->_returns[$method] = new CallMap(); 587 } 588 $this->_returns[$method]->addReference($args, $reference); 589 } 590 591 /** 592 * Sets a return for a parameter list that will 593 * be passed by value only when the required call count 594 * is reached. 595 * @param integer $timing Number of calls in the future 596 * to which the result applies. If 597 * not set then all calls will return 598 * the value. 599 * @param string $method Method name. 600 * @param mixed $reference Result of the call will be this object. 601 * @param array $args List of parameters to match 602 * including wildcards. 603 * @access public 604 */ 605 function setReturnReferenceAt($timing, $method, &$reference, $args = false) { 606 $this->_dieOnNoMethod($method, "set return reference sequence"); 607 $args = $this->_replaceWildcards($args); 608 $method = strtolower($method); 609 if (! isset($this->_return_sequence[$method])) { 610 $this->_return_sequence[$method] = array(); 611 } 612 if (! isset($this->_return_sequence[$method][$timing])) { 613 $this->_return_sequence[$method][$timing] = new CallMap(); 614 } 615 $this->_return_sequence[$method][$timing]->addReference($args, $reference); 616 } 617 618 /** 619 * Sets up an expected call with a set of 620 * expected parameters in that call. All 621 * calls will be compared to these expectations 622 * regardless of when the call is made. 623 * @param string $method Method call to test. 624 * @param array $args Expected parameters for the call 625 * including wildcards. 626 * @param string $message Overridden message. 627 * @access public 628 */ 629 function expect($method, $args, $message = '%s') { 630 $this->_dieOnNoMethod($method, 'set expected arguments'); 631 $this->_checkArgumentsIsArray($args, 'set expected arguments'); 632 $args = $this->_replaceWildcards($args); 633 $message .= Mock::getExpectationLine(); 634 $this->_expected_args[strtolower($method)] = 635 new ParametersExpectation($args, $message); 636 } 637 638 /** 639 * @deprecated 640 */ 641 function expectArguments($method, $args, $message = '%s') { 642 return $this->expect($method, $args, $message); 643 } 644 645 /** 646 * Sets up an expected call with a set of 647 * expected parameters in that call. The 648 * expected call count will be adjusted if it 649 * is set too low to reach this call. 650 * @param integer $timing Number of calls in the future at 651 * which to test. Next call is 0. 652 * @param string $method Method call to test. 653 * @param array $args Expected parameters for the call 654 * including wildcards. 655 * @param string $message Overridden message. 656 * @access public 657 */ 658 function expectAt($timing, $method, $args, $message = '%s') { 659 $this->_dieOnNoMethod($method, 'set expected arguments at time'); 660 $this->_checkArgumentsIsArray($args, 'set expected arguments at time'); 661 $args = $this->_replaceWildcards($args); 662 if (! isset($this->_expected_args_at[$timing])) { 663 $this->_expected_args_at[$timing] = array(); 664 } 665 $method = strtolower($method); 666 $message .= Mock::getExpectationLine(); 667 $this->_expected_args_at[$timing][$method] = 668 new ParametersExpectation($args, $message); 669 } 670 671 /** 672 * @deprecated 673 */ 674 function expectArgumentsAt($timing, $method, $args, $message = '%s') { 675 return $this->expectAt($timing, $method, $args, $message); 676 } 677 678 /** 679 * Sets an expectation for the number of times 680 * a method will be called. The tally method 681 * is used to check this. 682 * @param string $method Method call to test. 683 * @param integer $count Number of times it should 684 * have been called at tally. 685 * @param string $message Overridden message. 686 * @access public 687 */ 688 function expectCallCount($method, $count, $message = '%s') { 689 $this->_dieOnNoMethod($method, 'set expected call count'); 690 $message .= Mock::getExpectationLine(); 691 $this->_expected_counts[strtolower($method)] = 692 new CallCountExpectation($method, $count, $message); 693 } 694 695 /** 696 * Sets the number of times a method may be called 697 * before a test failure is triggered. 698 * @param string $method Method call to test. 699 * @param integer $count Most number of times it should 700 * have been called. 701 * @param string $message Overridden message. 702 * @access public 703 */ 704 function expectMaximumCallCount($method, $count, $message = '%s') { 705 $this->_dieOnNoMethod($method, 'set maximum call count'); 706 $message .= Mock::getExpectationLine(); 707 $this->_max_counts[strtolower($method)] = 708 new MaximumCallCountExpectation($method, $count, $message); 709 } 710 711 /** 712 * Sets the number of times to call a method to prevent 713 * a failure on the tally. 714 * @param string $method Method call to test. 715 * @param integer $count Least number of times it should 716 * have been called. 717 * @param string $message Overridden message. 718 * @access public 719 */ 720 function expectMinimumCallCount($method, $count, $message = '%s') { 721 $this->_dieOnNoMethod($method, 'set minimum call count'); 722 $message .= Mock::getExpectationLine(); 723 $this->_expected_counts[strtolower($method)] = 724 new MinimumCallCountExpectation($method, $count, $message); 725 } 726 727 /** 728 * Convenience method for barring a method 729 * call. 730 * @param string $method Method call to ban. 731 * @param string $message Overridden message. 732 * @access public 733 */ 734 function expectNever($method, $message = '%s') { 735 $this->expectMaximumCallCount($method, 0, $message); 736 } 737 738 /** 739 * Convenience method for a single method 740 * call. 741 * @param string $method Method call to track. 742 * @param array $args Expected argument list or 743 * false for any arguments. 744 * @param string $message Overridden message. 745 * @access public 746 */ 747 function expectOnce($method, $args = false, $message = '%s') { 748 $this->expectCallCount($method, 1, $message); 749 if ($args !== false) { 750 $this->expectArguments($method, $args, $message); 751 } 752 } 753 754 /** 755 * Convenience method for requiring a method 756 * call. 757 * @param string $method Method call to track. 758 * @param array $args Expected argument list or 759 * false for any arguments. 760 * @param string $message Overridden message. 761 * @access public 762 */ 763 function expectAtLeastOnce($method, $args = false, $message = '%s') { 764 $this->expectMinimumCallCount($method, 1, $message); 765 if ($args !== false) { 766 $this->expectArguments($method, $args, $message); 767 } 768 } 769 770 /** 771 * @deprecated 772 */ 773 function tally() { 774 } 775 776 /** 777 * Receives event from unit test that the current 778 * test method has finished. Totals up the call 779 * counts and triggers a test assertion if a test 780 * is present for expected call counts. 781 * @param string $test_method Current method name. 782 * @param SimpleTestCase $test Test to send message to. 783 * @access public 784 */ 785 function atTestEnd($test_method, &$test) { 786 foreach ($this->_expected_counts as $method => $expectation) { 787 $test->assert($expectation, $this->getCallCount($method)); 788 } 789 foreach ($this->_max_counts as $method => $expectation) { 790 if ($expectation->test($this->getCallCount($method))) { 791 $test->assert($expectation, $this->getCallCount($method)); 792 } 793 } 794 } 795 796 /** 797 * Returns the expected value for the method name 798 * and checks expectations. Will generate any 799 * test assertions as a result of expectations 800 * if there is a test present. 801 * @param string $method Name of method to simulate. 802 * @param array $args Arguments as an array. 803 * @return mixed Stored return. 804 * @access private 805 */ 806 function &_invoke($method, $args) { 807 $method = strtolower($method); 808 $step = $this->getCallCount($method); 809 $this->_addCall($method, $args); 810 $this->_checkExpectations($method, $args, $step); 811 $result = &$this->_getReturn($method, $args, $step); 812 return $result; 813 } 814 /** 815 * Finds the return value matching the incoming 816 * arguments. If there is no matching value found 817 * then an error is triggered. 818 * @param string $method Method name. 819 * @param array $args Calling arguments. 820 * @param integer $step Current position in the 821 * call history. 822 * @return mixed Stored return. 823 * @access protected 824 */ 825 function &_getReturn($method, $args, $step) { 826 if (isset($this->_return_sequence[$method][$step])) { 827 if ($this->_return_sequence[$method][$step]->isMatch($args)) { 828 $result = &$this->_return_sequence[$method][$step]->findFirstMatch($args); 829 return $result; 830 } 831 } 832 if (isset($this->_returns[$method])) { 833 $result = &$this->_returns[$method]->findFirstMatch($args); 834 return $result; 835 } 836 $null = null; 837 return $null; 838 } 839 840 /** 841 * Tests the arguments against expectations. 842 * @param string $method Method to check. 843 * @param array $args Argument list to match. 844 * @param integer $timing The position of this call 845 * in the call history. 846 * @access private 847 */ 848 function _checkExpectations($method, $args, $timing) { 849 $test = &$this->_getCurrentTestCase(); 850 if (isset($this->_max_counts[$method])) { 851 if (! $this->_max_counts[$method]->test($timing + 1)) { 852 $test->assert($this->_max_counts[$method], $timing + 1); 853 } 854 } 855 if (isset($this->_expected_args_at[$timing][$method])) { 856 $test->assert( 857 $this->_expected_args_at[$timing][$method], 858 $args, 859 "Mock method [$method] at [$timing] -> %s"); 860 } elseif (isset($this->_expected_args[$method])) { 861 $test->assert( 862 $this->_expected_args[$method], 863 $args, 864 "Mock method [$method] -> %s"); 865 } 866 } 867 } 868 869 /** 870 * Static methods only service class for code generation of 871 * mock objects. 872 * @package SimpleTest 873 * @subpackage MockObjects 874 */ 875 class Mock { 876 877 /** 878 * Factory for mock object classes. 879 * @access public 880 */ 881 function Mock() { 882 trigger_error('Mock factory methods are static.'); 883 } 884 885 /** 886 * Clones a class' interface and creates a mock version 887 * that can have return values and expectations set. 888 * @param string $class Class to clone. 889 * @param string $mock_class New class name. Default is 890 * the old name with "Mock" 891 * prepended. 892 * @param array $methods Additional methods to add beyond 893 * those in th cloned class. Use this 894 * to emulate the dynamic addition of 895 * methods in the cloned class or when 896 * the class hasn't been written yet. 897 * @static 898 * @access public 899 */ 900 function generate($class, $mock_class = false, $methods = false) { 901 $generator = new MockGenerator($class, $mock_class); 902 return $generator->generate($methods); 903 } 904 905 /** 906 * Generates a version of a class with selected 907 * methods mocked only. Inherits the old class 908 * and chains the mock methods of an aggregated 909 * mock object. 910 * @param string $class Class to clone. 911 * @param string $mock_class New class name. 912 * @param array $methods Methods to be overridden 913 * with mock versions. 914 * @static 915 * @access public 916 */ 917 function generatePartial($class, $mock_class, $methods) { 918 $generator = new MockGenerator($class, $mock_class); 919 return $generator->generatePartial($methods); 920 } 921 922 /** 923 * Uses a stack trace to find the line of an assertion. 924 * @access public 925 * @static 926 */ 927 function getExpectationLine() { 928 $trace = new SimpleStackTrace(array('expect')); 929 return $trace->traceMethod(); 930 } 931 } 932 933 /** 934 * @deprecated 935 */ 936 class Stub extends Mock { 937 } 938 939 /** 940 * Service class for code generation of mock objects. 941 * @package SimpleTest 942 * @subpackage MockObjects 943 */ 944 class MockGenerator { 945 var $_class; 946 var $_mock_class; 947 var $_mock_base; 948 var $_reflection; 949 950 function MockGenerator($class, $mock_class) { 951 $this->_class = $class; 952 $this->_mock_class = $mock_class; 953 $this->_mock_base = SimpleTest::getMockBaseClass(); 954 $this->_reflection = new SimpleReflection($this->_class); 955 } 956 957 /** 958 * Clones a class' interface and creates a mock version 959 * that can have return values and expectations set. 960 * @param array $methods Additional methods to add beyond 961 * those in th cloned class. Use this 962 * to emulate the dynamic addition of 963 * methods in the cloned class or when 964 * the class hasn't been written yet. 965 * @access public 966 */ 967 function generate($methods) { 968 if (! $this->_reflection->classOrInterfaceExists()) { 969 return false; 970 } 971 if (! $this->_mock_class) { 972 $this->_mock_class = 'Mock' . $this->_class; 973 } 974 $mock_reflection = new SimpleReflection($this->_mock_class); 975 if ($mock_reflection->classExistsSansAutoload()) { 976 return false; 977 } 978 return eval( 979 $this->_createClassCode($methods ? $methods : array()) . 980 " return true;"); 981 } 982 983 /** 984 * Generates a version of a class with selected 985 * methods mocked only. Inherits the old class 986 * and chains the mock methods of an aggregated 987 * mock object. 988 * @param array $methods Methods to be overridden 989 * with mock versions. 990 * @access public 991 */ 992 function generatePartial($methods) { 993 if (! $this->_reflection->classExists($this->_class)) { 994 return false; 995 } 996 $mock_reflection = new SimpleReflection($this->_mock_class); 997 if ($mock_reflection->classExistsSansAutoload()) { 998 trigger_error('Partial mock class [' . $this->_mock_class . '] already exists'); 999 return false; 1000 } 1001 return eval($this->_extendClassCode($methods)); 1002 } 1003 1004 /** 1005 * The new mock class code as a string. 1006 * @param array $methods Additional methods. 1007 * @return string Code for new mock class. 1008 * @access private 1009 */ 1010 function _createClassCode($methods) { 1011 $implements = ''; 1012 $interfaces = $this->_reflection->getInterfaces(); 1013 if (function_exists('spl_classes')) { 1014 $interfaces = array_diff($interfaces, array('Traversable')); 1015 } 1016 if (count($interfaces) > 0) { 1017 $implements = 'implements ' . implode(', ', $interfaces); 1018 } 1019 $code = "class " . $this->_mock_class . " extends " . $this->_mock_base . " $implements {\n"; 1020 $code .= " function " . $this->_mock_class . "() {\n"; 1021 $code .= " \$this->" . $this->_mock_base . "();\n"; 1022 $code .= " }\n"; 1023 $code .= $this->_createHandlerCode($methods); 1024 $code .= "}\n"; 1025 return $code; 1026 } 1027 1028 /** 1029 * The extension class code as a string. The class 1030 * composites a mock object and chains mocked methods 1031 * to it. 1032 * @param array $methods Mocked methods. 1033 * @return string Code for a new class. 1034 * @access private 1035 */ 1036 function _extendClassCode($methods) { 1037 $code = "class " . $this->_mock_class . " extends " . $this->_class . " {\n"; 1038 $code .= " var \$_mock;\n"; 1039 $code .= $this->_addMethodList($methods); 1040 $code .= "\n"; 1041 $code .= " function " . $this->_mock_class . "() {\n"; 1042 $code .= " \$this->_mock = &new " . $this->_mock_base . "();\n"; 1043 $code .= " \$this->_mock->disableExpectationNameChecks();\n"; 1044 $code .= " }\n"; 1045 $code .= $this->_chainMockReturns(); 1046 $code .= $this->_chainMockExpectations(); 1047 $code .= $this->_overrideMethods($methods); 1048 $code .= "}\n"; 1049 return $code; 1050 } 1051 1052 /** 1053 * Creates code within a class to generate replaced 1054 * methods. All methods call the _invoke() handler 1055 * with the method name and the arguments in an 1056 * array. 1057 * @param array $methods Additional methods. 1058 * @access private 1059 */ 1060 function _createHandlerCode($methods) { 1061 $code = ''; 1062 $methods = array_merge($methods, $this->_reflection->getMethods()); 1063 foreach ($methods as $method) { 1064 if ($this->_isConstructor($method)) { 1065 continue; 1066 } 1067 $mock_reflection = new SimpleReflection($this->_mock_base); 1068 if (in_array($method, $mock_reflection->getMethods())) { 1069 continue; 1070 } 1071 $code .= " " . $this->_reflection->getSignature($method) . " {\n"; 1072 $code .= " \$args = func_get_args();\n"; 1073 $code .= " \$result = &\$this->_invoke(\"$method\", \$args);\n"; 1074 $code .= " return \$result;\n"; 1075 $code .= " }\n"; 1076 } 1077 return $code; 1078 } 1079 1080 /** 1081 * Tests to see if a special PHP method is about to 1082 * be stubbed by mistake. 1083 * @param string $method Method name. 1084 * @return boolean True if special. 1085 * @access private 1086 */ 1087 function _isConstructor($method) { 1088 return in_array( 1089 strtolower($method), 1090 array('__construct', '__destruct', '__clone')); 1091 } 1092 1093 /** 1094 * Creates a list of mocked methods for error checking. 1095 * @param array $methods Mocked methods. 1096 * @return string Code for a method list. 1097 * @access private 1098 */ 1099 function _addMethodList($methods) { 1100 return " var \$_mocked_methods = array('" . implode("', '", $methods) . "');\n"; 1101 } 1102 1103 /** 1104 * Creates code to abandon the expectation if not mocked. 1105 * @param string $alias Parameter name of method name. 1106 * @return string Code for bail out. 1107 * @access private 1108 */ 1109 function _bailOutIfNotMocked($alias) { 1110 $code = " if (! in_array($alias, \$this->_mocked_methods)) {\n"; 1111 $code .= " trigger_error(\"Method [$alias] is not mocked\");\n"; 1112 $code .= " \$null = null;\n"; 1113 $code .= " return \$null;\n"; 1114 $code .= " }\n"; 1115 return $code; 1116 } 1117 1118 /** 1119 * Creates source code for chaining to the composited 1120 * mock object. 1121 * @return string Code for mock set up. 1122 * @access private 1123 */ 1124 function _chainMockReturns() { 1125 $code = " function setReturnValue(\$method, \$value, \$args = false) {\n"; 1126 $code .= $this->_bailOutIfNotMocked("\$method"); 1127 $code .= " \$this->_mock->setReturnValue(\$method, \$value, \$args);\n"; 1128 $code .= " }\n"; 1129 $code .= " function setReturnValueAt(\$timing, \$method, \$value, \$args = false) {\n"; 1130 $code .= $this->_bailOutIfNotMocked("\$method"); 1131 $code .= " \$this->_mock->setReturnValueAt(\$timing, \$method, \$value, \$args);\n"; 1132 $code .= " }\n"; 1133 $code .= " function setReturnReference(\$method, &\$ref, \$args = false) {\n"; 1134 $code .= $this->_bailOutIfNotMocked("\$method"); 1135 $code .= " \$this->_mock->setReturnReference(\$method, \$ref, \$args);\n"; 1136 $code .= " }\n"; 1137 $code .= " function setReturnReferenceAt(\$timing, \$method, &\$ref, \$args = false) {\n"; 1138 $code .= $this->_bailOutIfNotMocked("\$method"); 1139 $code .= " \$this->_mock->setReturnReferenceAt(\$timing, \$method, \$ref, \$args);\n"; 1140 $code .= " }\n"; 1141 return $code; 1142 } 1143 1144 /** 1145 * Creates source code for chaining to an aggregated 1146 * mock object. 1147 * @return string Code for expectations. 1148 * @access private 1149 */ 1150 function _chainMockExpectations() { 1151 $code = " function expect(\$method, \$args = false) {\n"; 1152 $code .= $this->_bailOutIfNotMocked("\$method"); 1153 $code .= " \$this->_mock->expect(\$method, \$args);\n"; 1154 $code .= " }\n"; 1155 $code .= " function expectArguments(\$method, \$args = false) {\n"; 1156 $code .= $this->_bailOutIfNotMocked("\$method"); 1157 $code .= " \$this->_mock->expectArguments(\$method, \$args);\n"; 1158 $code .= " }\n"; 1159 $code .= " function expectAt(\$timing, \$method, \$args = false) {\n"; 1160 $code .= $this->_bailOutIfNotMocked("\$method"); 1161 $code .= " \$this->_mock->expectArgumentsAt(\$timing, \$method, \$args);\n"; 1162 $code .= " }\n"; 1163 $code .= " function expectArgumentsAt(\$timing, \$method, \$args = false) {\n"; 1164 $code .= $this->_bailOutIfNotMocked("\$method"); 1165 $code .= " \$this->_mock->expectArgumentsAt(\$timing, \$method, \$args);\n"; 1166 $code .= " }\n"; 1167 $code .= " function expectCallCount(\$method, \$count) {\n"; 1168 $code .= $this->_bailOutIfNotMocked("\$method"); 1169 $code .= " \$this->_mock->expectCallCount(\$method, \$count);\n"; 1170 $code .= " }\n"; 1171 $code .= " function expectMaximumCallCount(\$method, \$count) {\n"; 1172 $code .= $this->_bailOutIfNotMocked("\$method"); 1173 $code .= " \$this->_mock->expectMaximumCallCount(\$method, \$count);\n"; 1174 $code .= " }\n"; 1175 $code .= " function expectMinimumCallCount(\$method, \$count) {\n"; 1176 $code .= $this->_bailOutIfNotMocked("\$method"); 1177 $code .= " \$this->_mock->expectMinimumCallCount(\$method, \$count);\n"; 1178 $code .= " }\n"; 1179 $code .= " function expectNever(\$method) {\n"; 1180 $code .= $this->_bailOutIfNotMocked("\$method"); 1181 $code .= " \$this->_mock->expectNever(\$method);\n"; 1182 $code .= " }\n"; 1183 $code .= " function expectOnce(\$method, \$args = false) {\n"; 1184 $code .= $this->_bailOutIfNotMocked("\$method"); 1185 $code .= " \$this->_mock->expectOnce(\$method, \$args);\n"; 1186 $code .= " }\n"; 1187 $code .= " function expectAtLeastOnce(\$method, \$args = false) {\n"; 1188 $code .= $this->_bailOutIfNotMocked("\$method"); 1189 $code .= " \$this->_mock->expectAtLeastOnce(\$method, \$args);\n"; 1190 $code .= " }\n"; 1191 $code .= " function tally() {\n"; 1192 $code .= " \$this->_mock->tally();\n"; 1193 $code .= " }\n"; 1194 return $code; 1195 } 1196 1197 /** 1198 * Creates source code to override a list of methods 1199 * with mock versions. 1200 * @param array $methods Methods to be overridden 1201 * with mock versions. 1202 * @return string Code for overridden chains. 1203 * @access private 1204 */ 1205 function _overrideMethods($methods) { 1206 $code = ""; 1207 foreach ($methods as $method) { 1208 $code .= " " . $this->_reflection->getSignature($method) . " {\n"; 1209 $code .= " \$args = func_get_args();\n"; 1210 $code .= " \$result = &\$this->_mock->_invoke(\"$method\", \$args);\n"; 1211 $code .= " return \$result;\n"; 1212 $code .= " }\n"; 1213 } 1214 return $code; 1215 } 1216 } 1217 ?>
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
| Generated: Wed Jan 14 11:33:29 2009 | Cross-referenced by PHPXref 0.7 |