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