3 * base include file for SimpleTest
5 * @subpackage MockObjects
6 * @version $Id: mock_objects.php,v 1.49 2004/08/18 19:10:54 lastcraft Exp $
10 * include SimpleTest files
12 require_once(dirname(__FILE__
) . '/expectation.php');
13 require_once(dirname(__FILE__
) . '/options.php');
14 require_once(dirname(__FILE__
) . '/dumper.php');
18 * Default character simpletest will substitute for any value
20 define('MOCK_WILDCARD', '*');
23 * A wildcard expectation always matches.
25 * @subpackage MockObjects
27 class WildcardExpectation
extends SimpleExpectation
{
30 * Chains constructor only.
33 function WildcardExpectation() {
34 $this->SimpleExpectation();
38 * Tests the expectation. Always true.
39 * @param mixed $compare Ignored.
40 * @return boolean True.
43 function test($compare) {
48 * Returns a human readable test message.
49 * @param mixed $compare Comparison value.
50 * @return string Description of success
54 function testMessage($compare) {
55 $dumper = &$this->_getDumper();
56 return 'Wildcard always matches [' . $dumper->describeValue($compare) . ']';
61 * Parameter comparison assertion.
63 * @subpackage MockObjects
65 class ParametersExpectation
extends SimpleExpectation
{
69 * Sets the expected parameter list.
70 * @param array $parameters Array of parameters including
71 * those that are wildcarded.
72 * If the value is not an array
73 * then it is considered to match any.
74 * @param mixed $wildcard Any parameter matching this
76 * @param string $message Customised message on failure.
79 function ParametersExpectation($expected = false
, $message = '%s') {
80 $this->SimpleExpectation($message);
81 $this->_expected
= $expected;
85 * Tests the assertion. True if correct.
86 * @param array $parameters Comparison values.
87 * @return boolean True if correct.
90 function test($parameters) {
91 if (! is_array($this->_expected
)) {
94 if (count($this->_expected
) != count($parameters)) {
97 for ($i = 0; $i < count($this->_expected
); $i++
) {
98 if (! $this->_testParameter($parameters[$i], $this->_expected
[$i])) {
106 * Tests an individual parameter.
107 * @param mixed $parameter Value to test.
108 * @param mixed $expected Comparison value.
109 * @return boolean True if expectation
113 function _testParameter($parameter, $expected) {
114 $comparison = $this->_coerceToExpectation($expected);
115 return $comparison->test($parameter);
119 * Returns a human readable test message.
120 * @param array $comparison Incoming parameter list.
121 * @return string Description of success
125 function testMessage($parameters) {
126 if ($this->test($parameters)) {
127 return "Expectation of " . count($this->_expected
) .
128 " arguments of [" . $this->_renderArguments($this->_expected
) .
131 return $this->_describeDifference($this->_expected
, $parameters);
136 * Message to display if expectation differs from
137 * the parameters actually received.
138 * @param array $expected Expected parameters as list.
139 * @param array $parameters Actual parameters received.
140 * @return string Description of difference.
143 function _describeDifference($expected, $parameters) {
144 if (count($expected) != count($parameters)) {
145 return "Expected " . count($expected) .
146 " arguments of [" . $this->_renderArguments($expected) .
147 "] but got " . count($parameters) .
148 " arguments of [" . $this->_renderArguments($parameters) . "]";
151 for ($i = 0; $i < count($expected); $i++
) {
152 $comparison = $this->_coerceToExpectation($expected[$i]);
153 if (! $comparison->test($parameters[$i])) {
154 $messages[] = "parameter " . ($i +
1) . " with [" .
155 $comparison->overlayMessage($parameters[$i]) . "]";
158 return "Parameter expectation differs at " . implode(" and ", $messages);
162 * Creates an identical expectation if the
163 * object/value is not already some type
165 * @param mixed $expected Expected value.
166 * @return SimpleExpectation Expectation object.
169 function _coerceToExpectation($expected) {
170 if (SimpleTestCompatibility
::isA($expected, 'SimpleExpectation')) {
173 return new IdenticalExpectation($expected);
177 * Renders the argument list as a string for
179 * @param array $args Incoming arguments.
180 * @return string Simple description of type and value.
183 function _renderArguments($args) {
184 $descriptions = array();
185 if (is_array($args)) {
186 foreach ($args as $arg) {
187 $dumper = &new SimpleDumper();
188 $descriptions[] = $dumper->describeValue($arg);
191 return implode(', ', $descriptions);
196 * Confirms that the number of calls on a method is as expected.
198 class CallCountExpectation
extends SimpleExpectation
{
203 * Stashes the method and expected count for later
205 * @param string $method Name of method to confirm against.
206 * @param integer $count Expected number of calls.
207 * @param string $message Custom error message.
209 function CallCountExpectation($method, $count, $message = '%s') {
210 $this->_method
= $method;
211 $this->_count
= $count;
212 $this->SimpleExpectation($message);
216 * Tests the assertion. True if correct.
217 * @param integer $compare Measured call count.
218 * @return boolean True if expected.
221 function test($compare) {
222 return ($this->_count
== $compare);
226 * Reports the comparison.
227 * @param integer $compare Measured call count.
228 * @return string Message to show.
231 function testMessage($compare) {
232 return 'Expected call count for [' . $this->_method
.
233 '] was [' . $this->_count
.
234 '] got [' . $compare . ']';
239 * Confirms that the number of calls on a method is as expected.
241 class MinimumCallCountExpectation
extends SimpleExpectation
{
246 * Stashes the method and expected count for later
248 * @param string $method Name of method to confirm against.
249 * @param integer $count Minimum number of calls.
250 * @param string $message Custom error message.
252 function MinimumCallCountExpectation($method, $count, $message = '%s') {
253 $this->_method
= $method;
254 $this->_count
= $count;
255 $this->SimpleExpectation($message);
259 * Tests the assertion. True if correct.
260 * @param integer $compare Measured call count.
261 * @return boolean True if enough.
264 function test($compare) {
265 return ($this->_count
<= $compare);
269 * Reports the comparison.
270 * @param integer $compare Measured call count.
271 * @return string Message to show.
274 function testMessage($compare) {
275 return 'Minimum call count for [' . $this->_method
.
276 '] was [' . $this->_count
.
277 '] got [' . $compare . ']';
282 * Confirms that the number of calls on a method is as expected.
284 class MaximumCallCountExpectation
extends SimpleExpectation
{
289 * Stashes the method and expected count for later
291 * @param string $method Name of method to confirm against.
292 * @param integer $count Minimum number of calls.
293 * @param string $message Custom error message.
295 function MaximumCallCountExpectation($method, $count, $message = '%s') {
296 $this->_method
= $method;
297 $this->_count
= $count;
298 $this->SimpleExpectation($message);
302 * Tests the assertion. True if correct.
303 * @param integer $compare Measured call count.
304 * @return boolean True if not over.
307 function test($compare) {
308 return ($this->_count
>= $compare);
312 * Reports the comparison.
313 * @param integer $compare Measured call count.
314 * @return string Message to show.
317 function testMessage($compare) {
318 return 'Miximum call count for [' . $this->_method
.
319 '] was [' . $this->_count
.
320 '] got [' . $compare . ']';
325 * Retrieves values and references by searching the
326 * parameter lists until a match is found.
327 * @package SimpleTest
328 * @subpackage MockObjects
334 * Creates an empty call map.
338 $this->_map
= array();
342 * Stashes a value against a method call.
343 * @param array $parameters Arguments including wildcards.
344 * @param mixed $value Value copied into the map.
347 function addValue($parameters, $value) {
348 $this->addReference($parameters, $value);
352 * Stashes a reference against a method call.
353 * @param array $parameters Array of arguments (including wildcards).
354 * @param mixed $reference Array reference placed in the map.
357 function addReference($parameters, &$reference) {
358 $place = count($this->_map
);
359 $this->_map
[$place] = array();
360 $this->_map
[$place]["params"] = new ParametersExpectation($parameters);
361 $this->_map
[$place]["content"] = &$reference;
365 * Searches the call list for a matching parameter
366 * set. Returned by reference.
367 * @param array $parameters Parameters to search by
369 * @return object Object held in the first matching
370 * slot, otherwise null.
373 function &findFirstMatch($parameters) {
374 $slot = $this->_findFirstSlot($parameters);
378 return $slot["content"];
382 * Searches the call list for a matching parameter
383 * set. True if successful.
384 * @param array $parameters Parameters to search by
386 * @return boolean True if a match is present.
389 function isMatch($parameters) {
390 return ($this->_findFirstSlot($parameters) != null
);
394 * Searches the map for a matching item.
395 * @param array $parameters Parameters to search by
397 * @return array Reference to slot or null.
400 function &_findFirstSlot($parameters) {
401 for ($i = 0; $i < count($this->_map
); $i++
) {
402 if ($this->_map
[$i]["params"]->test($parameters)) {
403 return $this->_map
[$i];
411 * An empty collection of methods that can have their
412 * return values set. Used for prototyping.
413 * @package SimpleTest
414 * @subpackage MockObjects
420 var $_return_sequence;
424 * Sets up the wildcard and everything else empty.
425 * @param mixed $wildcard Parameter matching wildcard.
426 * @param boolean $is_strict Enables method name checks.
429 function SimpleStub($wildcard, $is_strict = true
) {
430 $this->_wildcard
= $wildcard;
431 $this->_is_strict
= $is_strict;
432 $this->_returns
= array();
433 $this->_return_sequence
= array();
434 $this->_call_counts
= array();
438 * Replaces wildcard matches with wildcard
439 * expectations in the argument list.
440 * @param array $args Raw argument list.
441 * @return array Argument list with
445 function _replaceWildcards($args) {
446 if ($args === false
) {
449 for ($i = 0; $i < count($args); $i++
) {
450 if ($args[$i] === $this->_wildcard
) {
451 $args[$i] = new WildcardExpectation();
458 * Returns the expected value for the method name.
459 * @param string $method Name of method to simulate.
460 * @param array $args Arguments as an array.
461 * @return mixed Stored return.
464 function &_invoke($method, $args) {
465 $method = strtolower($method);
466 $step = $this->getCallCount($method);
467 $this->_addCall($method, $args);
468 return $this->_getReturn($method, $args, $step);
472 * Triggers a PHP error if the method is not part
474 * @param string $method Name of method.
475 * @param string $task Description of task attempt.
478 function _dieOnNoMethod($method, $task) {
479 if ($this->_is_strict
&& !method_exists($this, $method)) {
481 "Cannot $task as no ${method}() in class " . get_class($this),
487 * Adds one to the call count of a method.
488 * @param string $method Method called.
489 * @param array $args Arguments as an array.
492 function _addCall($method, $args) {
493 if (!isset($this->_call_counts
[$method])) {
494 $this->_call_counts
[$method] = 0;
496 $this->_call_counts
[$method]++
;
500 * Fetches the call count of a method so far.
501 * @param string $method Method name called.
502 * @return Number of calls so far.
505 function getCallCount($method) {
506 $this->_dieOnNoMethod($method, "get call count");
507 $method = strtolower($method);
508 if (! isset($this->_call_counts
[$method])) {
511 return $this->_call_counts
[$method];
515 * Sets a return for a parameter list that will
516 * be passed by value for all calls to this method.
517 * @param string $method Method name.
518 * @param mixed $value Result of call passed by value.
519 * @param array $args List of parameters to match
520 * including wildcards.
523 function setReturnValue($method, $value, $args = false
) {
524 $this->_dieOnNoMethod($method, "set return value");
525 $args = $this->_replaceWildcards($args);
526 $method = strtolower($method);
527 if (! isset($this->_returns
[$method])) {
528 $this->_returns
[$method] = new CallMap();
530 $this->_returns
[$method]->addValue($args, $value);
534 * Sets a return for a parameter list that will
535 * be passed by value only when the required call count
537 * @param integer $timing Number of calls in the future
538 * to which the result applies. If
539 * not set then all calls will return
541 * @param string $method Method name.
542 * @param mixed $value Result of call passed by value.
543 * @param array $args List of parameters to match
544 * including wildcards.
547 function setReturnValueAt($timing, $method, $value, $args = false
) {
548 $this->_dieOnNoMethod($method, "set return value sequence");
549 $args = $this->_replaceWildcards($args);
550 $method = strtolower($method);
551 if (! isset($this->_return_sequence
[$method])) {
552 $this->_return_sequence
[$method] = array();
554 if (! isset($this->_return_sequence
[$method][$timing])) {
555 $this->_return_sequence
[$method][$timing] = new CallMap();
557 $this->_return_sequence
[$method][$timing]->addValue($args, $value);
561 * Sets a return for a parameter list that will
562 * be passed by reference for all calls.
563 * @param string $method Method name.
564 * @param mixed $reference Result of the call will be this object.
565 * @param array $args List of parameters to match
566 * including wildcards.
569 function setReturnReference($method, &$reference, $args = false
) {
570 $this->_dieOnNoMethod($method, "set return reference");
571 $args = $this->_replaceWildcards($args);
572 $method = strtolower($method);
573 if (! isset($this->_returns
[$method])) {
574 $this->_returns
[$method] = new CallMap();
576 $this->_returns
[$method]->addReference($args, $reference);
580 * Sets a return for a parameter list that will
581 * be passed by value only when the required call count
583 * @param integer $timing Number of calls in the future
584 * to which the result applies. If
585 * not set then all calls will return
587 * @param string $method Method name.
588 * @param mixed $reference Result of the call will be this object.
589 * @param array $args List of parameters to match
590 * including wildcards.
593 function setReturnReferenceAt($timing, $method, &$reference, $args = false
) {
594 $this->_dieOnNoMethod($method, "set return reference sequence");
595 $args = $this->_replaceWildcards($args);
596 $method = strtolower($method);
597 if (! isset($this->_return_sequence
[$method])) {
598 $this->_return_sequence
[$method] = array();
600 if (! isset($this->_return_sequence
[$method][$timing])) {
601 $this->_return_sequence
[$method][$timing] = new CallMap();
603 $this->_return_sequence
[$method][$timing]->addReference($args, $reference);
607 * Finds the return value matching the incoming
608 * arguments. If there is no matching value found
609 * then an error is triggered.
610 * @param string $method Method name.
611 * @param array $args Calling arguments.
612 * @param integer $step Current position in the
614 * @return mixed Stored return.
617 function &_getReturn($method, $args, $step) {
618 if (isset($this->_return_sequence
[$method][$step])) {
619 if ($this->_return_sequence
[$method][$step]->isMatch($args)) {
620 return $this->_return_sequence
[$method][$step]->findFirstMatch($args);
623 if (isset($this->_returns
[$method])) {
624 return $this->_returns
[$method]->findFirstMatch($args);
631 * An empty collection of methods that can have their
632 * return values set and expectations made of the
633 * calls upon them. The mock will assert the
634 * expectations against it's attached test case in
635 * addition to the server stub behaviour.
636 * @package SimpleTest
637 * @subpackage MockObjects
639 class SimpleMock
extends SimpleStub
{
641 var $_expected_counts;
644 var $_expected_args_at;
647 * Creates an empty return list and expectation list.
648 * All call counts are set to zero.
649 * @param SimpleTestCase $test Test case to test expectations in.
650 * @param mixed $wildcard Parameter matching wildcard.
651 * @param boolean $is_strict Enables method name checks on
655 function SimpleMock(&$test, $wildcard, $is_strict = true
) {
656 $this->SimpleStub($wildcard, $is_strict);
658 trigger_error('No unit tester for mock object', E_USER_ERROR
);
661 $this->_test
= &$test;
662 $this->_expected_counts
= array();
663 $this->_max_counts
= array();
664 $this->_expected_args
= array();
665 $this->_expected_args_at
= array();
669 * Accessor for attached unit test so that when
670 * subclassed, new expectations can be added easily.
671 * @return SimpleTestCase Unit test passed in constructor.
674 function &getTest() {
679 * Die if bad arguments array is passed
680 * @param mixed $args The arguments value to be checked.
681 * @param string $task Description of task attempt.
682 * @return boolean Valid arguments
685 function _checkArgumentsIsArray($args, $task) {
686 if (! is_array($args)) {
688 "Cannot $task as \$args parameter is not an array",
694 * Sets up an expected call with a set of
695 * expected parameters in that call. All
696 * calls will be compared to these expectations
697 * regardless of when the call is made.
698 * @param string $method Method call to test.
699 * @param array $args Expected parameters for the call
700 * including wildcards.
701 * @param string $message Overridden message.
704 function expectArguments($method, $args, $message = '%s') {
705 $this->_dieOnNoMethod($method, 'set expected arguments');
706 $this->_checkArgumentsIsArray($args, 'set expected arguments');
707 $args = $this->_replaceWildcards($args);
708 $message .= Mock
::getExpectationLine(' at line [%d]');
709 $this->_expected_args
[strtolower($method)] =
710 new ParametersExpectation($args, $message);
714 * Sets up an expected call with a set of
715 * expected parameters in that call. The
716 * expected call count will be adjusted if it
717 * is set too low to reach this call.
718 * @param integer $timing Number of calls in the future at
719 * which to test. Next call is 0.
720 * @param string $method Method call to test.
721 * @param array $args Expected parameters for the call
722 * including wildcards.
723 * @param string $message Overridden message.
726 function expectArgumentsAt($timing, $method, $args, $message = '%s') {
727 $this->_dieOnNoMethod($method, "set expected arguments at time");
728 $this->_checkArgumentsIsArray($args, "set expected arguments");
729 $args = $this->_replaceWildcards($args);
730 if (! isset($this->_expected_args_at
[$timing])) {
731 $this->_expected_args_at
[$timing] = array();
733 $method = strtolower($method);
734 $message .= Mock
::getExpectationLine(' at line [%d]');
735 $this->_expected_args_at
[$timing][$method] =
736 new ParametersExpectation($args, $message);
740 * Sets an expectation for the number of times
741 * a method will be called. The tally method
742 * is used to check this.
743 * @param string $method Method call to test.
744 * @param integer $count Number of times it should
745 * have been called at tally.
746 * @param string $message Overridden message.
749 function expectCallCount($method, $count, $message = '%s') {
750 $this->_dieOnNoMethod($method, "set expected call count");
751 $message .= Mock
::getExpectationLine(' at line [%d]');
752 $this->_expected_counts
[strtolower($method)] =
753 new CallCountExpectation($method, $count, $message);
757 * Sets the number of times a method may be called
758 * before a test failure is triggered.
759 * @param string $method Method call to test.
760 * @param integer $count Most number of times it should
762 * @param string $message Overridden message.
765 function expectMaximumCallCount($method, $count, $message = '%s') {
766 $this->_dieOnNoMethod($method, "set maximum call count");
767 $message .= Mock
::getExpectationLine(' at line [%d]');
768 $this->_max_counts
[strtolower($method)] =
769 new MaximumCallCountExpectation($method, $count, $message);
773 * Sets the number of times to call a method to prevent
774 * a failure on the tally.
775 * @param string $method Method call to test.
776 * @param integer $count Least number of times it should
778 * @param string $message Overridden message.
781 function expectMinimumCallCount($method, $count, $message = '%s') {
782 $this->_dieOnNoMethod($method, "set minimum call count");
783 $message .= Mock
::getExpectationLine(' at line [%d]');
784 $this->_expected_counts
[strtolower($method)] =
785 new MinimumCallCountExpectation($method, $count, $message);
789 * Convenience method for barring a method
791 * @param string $method Method call to ban.
792 * @param string $message Overridden message.
795 function expectNever($method, $message = '%s') {
796 $this->expectMaximumCallCount($method, 0, $message);
800 * Convenience method for a single method
802 * @param string $method Method call to track.
803 * @param array $args Expected argument list or
804 * false for any arguments.
805 * @param string $message Overridden message.
808 function expectOnce($method, $args = false
, $message = '%s') {
809 $this->expectCallCount($method, 1, $message);
810 if ($args !== false
) {
811 $this->expectArguments($method, $args, $message);
816 * Convenience method for requiring a method
818 * @param string $method Method call to track.
819 * @param array $args Expected argument list or
820 * false for any arguments.
821 * @param string $message Overridden message.
824 function expectAtLeastOnce($method, $args = false
, $message = '%s') {
825 $this->expectMinimumCallCount($method, 1, $message);
826 if ($args !== false
) {
827 $this->expectArguments($method, $args, $message);
832 * Totals up the call counts and triggers a test
833 * assertion if a test is present for expected
835 * This method must be called explicitly for the call
836 * count assertions to be triggered.
840 foreach ($this->_expected_counts
as $method => $expectation) {
842 $expectation->test($this->getCallCount($method)),
843 $expectation->overlayMessage($this->getCallCount($method)));
848 * Returns the expected value for the method name
849 * and checks expectations. Will generate any
850 * test assertions as a result of expectations
851 * if there is a test present.
852 * @param string $method Name of method to simulate.
853 * @param array $args Arguments as an array.
854 * @return mixed Stored return.
857 function &_invoke($method, $args) {
858 $method = strtolower($method);
859 $step = $this->getCallCount($method);
860 $this->_addCall($method, $args);
861 $this->_checkExpectations($method, $args, $step);
862 return $this->_getReturn($method, $args, $step);
866 * Tests the arguments against expectations.
867 * @param string $method Method to check.
868 * @param array $args Argument list to match.
869 * @param integer $timing The position of this call
870 * in the call history.
873 function _checkExpectations($method, $args, $timing) {
874 if (isset($this->_max_counts
[$method])) {
875 if (! $this->_max_counts
[$method]->test($timing +
1)) {
878 $this->_max_counts
[$method]->overlayMessage($timing +
1));
881 if (isset($this->_expected_args_at
[$timing][$method])) {
883 $this->_expected_args_at
[$timing][$method]->test($args),
884 "Mock method [$method] at [$timing] -> " .
885 $this->_expected_args_at
[$timing][$method]->overlayMessage($args));
886 } elseif (isset($this->_expected_args
[$method])) {
888 $this->_expected_args
[$method]->test($args),
889 "Mock method [$method] -> " . $this->_expected_args
[$method]->overlayMessage($args));
894 * Triggers an assertion on the held test case.
895 * Should be overridden when using another test
896 * framework other than the SimpleTest one if the
897 * assertion method has a different name.
898 * @param boolean $assertion True will pass.
899 * @param string $message Message that will go with
903 function _assertTrue($assertion, $message) {
904 $this->_test
->assertTrue($assertion, $message);
909 * Static methods only service class for code generation of
911 * @package SimpleTest
912 * @subpackage MockObjects
917 * Factory for server stub classes.
920 trigger_error('Stub factory methods are class only.');
924 * Clones a class' interface and creates a stub version
925 * that can have return values set.
926 * @param string $class Class to clone.
927 * @param string $stub_class New class name. Default is
928 * the old name with "Stub"
930 * @param array $methods Additional methods to add beyond
931 * those in th cloned class. Use this
932 * to emulate the dynamic addition of
933 * methods in the cloned class or when
934 * the class hasn't been written yet.
938 function generate($class, $stub_class = false
, $methods = false
) {
939 if (! class_exists($class)) {
943 $stub_class = "Stub" . $class;
945 if (class_exists($stub_class)) {
948 return eval(Stub
::_createClassCode(
951 $methods ?
$methods : array()) . " return true;");
955 * The new server stub class code in string form.
956 * @param string $class Class to clone.
957 * @param string $mock_class New class name.
958 * @param array $methods Additional methods.
962 function _createClassCode($class, $stub_class, $methods) {
963 $stub_base = SimpleTestOptions
::getStubBaseClass();
964 $code = "class $stub_class extends $stub_base {\n";
965 $code .= " function $stub_class(\$wildcard = MOCK_WILDCARD) {\n";
966 $code .= " \$this->$stub_base(\$wildcard);\n";
968 $code .= Stub
::_createHandlerCode($class, $stub_base, $methods);
974 * Creates code within a class to generate replaced
975 * methods. All methods call the _invoke() handler
976 * with the method name and the arguments in an
978 * @param string $class Class to clone.
979 * @param string $base Base class with methods that
981 * @param array $methods Additional methods.
985 function _createHandlerCode($class, $base, $methods) {
987 $methods = array_merge($methods, get_class_methods($class));
988 foreach ($methods as $method) {
989 if (($method == '__construct') ||
($method == '__clone')) {
992 if (in_array($method, get_class_methods($base))) {
995 $code .= " function &$method() {\n";
996 $code .= " \$args = func_get_args();\n";
997 $code .= " return \$this->_invoke(\"$method\", \$args);\n";
1005 * Static methods only service class for code generation of
1007 * @package SimpleTest
1008 * @subpackage MockObjects
1013 * Factory for mock object classes.
1017 trigger_error("Mock factory methods are class only.");
1021 * Clones a class' interface and creates a mock version
1022 * that can have return values and expectations set.
1023 * @param string $class Class to clone.
1024 * @param string $mock_class New class name. Default is
1025 * the old name with "Mock"
1027 * @param array $methods Additional methods to add beyond
1028 * those in th cloned class. Use this
1029 * to emulate the dynamic addition of
1030 * methods in the cloned class or when
1031 * the class hasn't been written yet.
1035 function generate($class, $mock_class = false
, $methods = false
) {
1036 if (! class_exists($class)) {
1039 if (! $mock_class) {
1040 $mock_class = "Mock" . $class;
1042 if (class_exists($mock_class)) {
1045 return eval(Mock
::_createClassCode(
1048 $methods ?
$methods : array()) . " return true;");
1052 * Generates a version of a class with selected
1053 * methods mocked only. Inherits the old class
1054 * and chains the mock methods of an aggregated
1056 * @param string $class Class to clone.
1057 * @param string $mock_class New class name.
1058 * @param array $methods Methods to be overridden
1059 * with mock versions.
1063 function generatePartial($class, $mock_class, $methods) {
1064 if (! class_exists($class)) {
1067 if (class_exists($mock_class)) {
1068 trigger_error("Partial mock class [$mock_class] already exists");
1071 return eval(Mock
::_extendClassCode($class, $mock_class, $methods));
1075 * The new mock class code as a string.
1076 * @param string $class Class to clone.
1077 * @param string $mock_class New class name.
1078 * @param array $methods Additional methods.
1079 * @return string Code for new mock class.
1083 function _createClassCode($class, $mock_class, $methods) {
1084 $mock_base = SimpleTestOptions
::getMockBaseClass();
1085 $code = "class $mock_class extends $mock_base {\n";
1086 $code .= " function $mock_class(&\$test, \$wildcard = MOCK_WILDCARD) {\n";
1087 $code .= " \$this->$mock_base(\$test, \$wildcard);\n";
1089 $code .= Stub
::_createHandlerCode($class, $mock_base, $methods);
1095 * The extension class code as a string. The class
1096 * composites a mock object and chains mocked methods
1098 * @param string $class Class to extend.
1099 * @param string $mock_class New class name.
1100 * @param array $methods Mocked methods.
1101 * @return string Code for a new class.
1105 function _extendClassCode($class, $mock_class, $methods) {
1106 $mock_base = SimpleTestOptions
::getMockBaseClass();
1107 $code = "class $mock_class extends $class {\n";
1108 $code .= " var \$_mock;\n";
1109 $code .= Mock
::_addMethodList($methods);
1111 $code .= " function $mock_class(&\$test, \$wildcard = MOCK_WILDCARD) {\n";
1112 $code .= " \$this->_mock = &new $mock_base(\$test, \$wildcard, false);\n";
1114 $code .= Mock
::_chainMockReturns();
1115 $code .= Mock
::_chainMockExpectations();
1116 $code .= Mock
::_overrideMethods($methods);
1117 $code .= SimpleTestOptions
::getPartialMockCode();
1123 * Creates a list of mocked methods for error checking.
1124 * @param array $methods Mocked methods.
1125 * @return string Code for a method list.
1128 function _addMethodList($methods) {
1129 return " var \$_mocked_methods = array('" .
1130 implode("', '", $methods) . "');\n";
1134 * Creates code to abandon the expectation if not mocked.
1135 * @param string $alias Parameter name of method name.
1136 * @return string Code for bail out.
1139 function _bailOutIfNotMocked($alias) {
1140 $code = " if (! in_array($alias, \$this->_mocked_methods)) {\n";
1141 $code .= " trigger_error('Method [$alias] is not mocked');\n";
1142 $code .= " return;\n";
1148 * Creates source code for chaining to the composited
1150 * @return string Code for mock set up.
1153 function _chainMockReturns() {
1154 $code = " function setReturnValue(\$method, \$value, \$args = false) {\n";
1155 $code .= Mock
::_bailOutIfNotMocked("\$method");
1156 $code .= " \$this->_mock->setReturnValue(\$method, \$value, \$args);\n";
1158 $code .= " function setReturnValueAt(\$timing, \$method, \$value, \$args = false) {\n";
1159 $code .= Mock
::_bailOutIfNotMocked("\$method");
1160 $code .= " \$this->_mock->setReturnValueAt(\$timing, \$method, \$value, \$args);\n";
1162 $code .= " function setReturnReference(\$method, &\$ref, \$args = false) {\n";
1163 $code .= Mock
::_bailOutIfNotMocked("\$method");
1164 $code .= " \$this->_mock->setReturnReference(\$method, \$ref, \$args);\n";
1166 $code .= " function setReturnReferenceAt(\$timing, \$method, &\$ref, \$args = false) {\n";
1167 $code .= Mock
::_bailOutIfNotMocked("\$method");
1168 $code .= " \$this->_mock->setReturnReferenceAt(\$timing, \$method, \$ref, \$args);\n";
1174 * Creates source code for chaining to an aggregated
1176 * @return string Code for expectations.
1179 function _chainMockExpectations() {
1180 $code = " function expectArguments(\$method, \$args = false) {\n";
1181 $code .= Mock
::_bailOutIfNotMocked("\$method");
1182 $code .= " \$this->_mock->expectArguments(\$method, \$args);\n";
1184 $code .= " function expectArgumentsAt(\$timing, \$method, \$args = false) {\n";
1185 $code .= Mock
::_bailOutIfNotMocked("\$method");
1186 $code .= " \$this->_mock->expectArgumentsAt(\$timing, \$method, \$args);\n";
1188 $code .= " function expectCallCount(\$method, \$count) {\n";
1189 $code .= Mock
::_bailOutIfNotMocked("\$method");
1190 $code .= " \$this->_mock->expectCallCount(\$method, \$count);\n";
1192 $code .= " function expectMaximumCallCount(\$method, \$count) {\n";
1193 $code .= Mock
::_bailOutIfNotMocked("\$method");
1194 $code .= " \$this->_mock->expectMaximumCallCount(\$method, \$count);\n";
1196 $code .= " function expectMinimumCallCount(\$method, \$count) {\n";
1197 $code .= Mock
::_bailOutIfNotMocked("\$method");
1198 $code .= " \$this->_mock->expectMinimumCallCount(\$method, \$count);\n";
1200 $code .= " function expectNever(\$method) {\n";
1201 $code .= Mock
::_bailOutIfNotMocked("\$method");
1202 $code .= " \$this->_mock->expectNever(\$method);\n";
1204 $code .= " function expectOnce(\$method, \$args = false) {\n";
1205 $code .= Mock
::_bailOutIfNotMocked("\$method");
1206 $code .= " \$this->_mock->expectOnce(\$method, \$args);\n";
1208 $code .= " function expectAtLeastOnce(\$method, \$args = false) {\n";
1209 $code .= Mock
::_bailOutIfNotMocked("\$method");
1210 $code .= " \$this->_mock->expectAtLeastOnce(\$method, \$args);\n";
1212 $code .= " function tally() {\n";
1213 $code .= " \$this->_mock->tally();\n";
1219 * Creates source code to override a list of methods
1220 * with mock versions.
1221 * @param array $methods Methods to be overridden
1222 * with mock versions.
1223 * @return string Code for overridden chains.
1226 function _overrideMethods($methods) {
1228 foreach ($methods as $method) {
1229 $code .= " function &$method() {\n";
1230 $code .= " \$args = func_get_args();\n";
1231 $code .= " return \$this->_mock->_invoke(\"$method\", \$args);\n";
1238 * Uses a stack trace to find the line of an assertion.
1239 * @param string $format String formatting.
1240 * @param array $stack Stack frames top most first. Only
1241 * needed if not using the PHP
1242 * backtrace function.
1243 * @return string Line number of first assert*
1244 * method embedded in format string.
1248 function getExpectationLine($format = '%d', $stack = false
) {
1249 if ($stack === false
) {
1250 $stack = SimpleTestCompatibility
::getStackTrace();
1252 return SimpleDumper
::getFormattedAssertionLine($stack, $format, 'expect');