mock_objects.php
来自「一款可以和GOOGLE媲美的开源统计系统,运用AJAX.功能强大. 无色提示:」· PHP 代码 · 共 1,307 行 · 第 1/4 页
PHP
1,307 行
/** * Subclasses a class and overrides every method with a mock one * that can have return values and expectations set. Chains * to an aggregated SimpleMock. * @param array $methods Additional methods to add beyond * those in the cloned class. Use this * to emulate the dynamic addition of * methods in the cloned class or when * the class hasn't been written yet. * @access public */ function generateSubclass($methods) { if (! $this->_reflection->classOrInterfaceExists()) { return false; } $mock_reflection = new SimpleReflection($this->_mock_class); if ($mock_reflection->classExistsSansAutoload()) { return false; } if ($this->_reflection->isInterface() || $this->_reflection->hasFinal()) { $code = $this->_createClassCode($methods ? $methods : array()); return eval("$code return \$code;"); } else { $code = $this->_createSubclassCode($methods ? $methods : array()); return eval("$code return \$code;"); } } /** * Generates a version of a class with selected * methods mocked only. Inherits the old class * and chains the mock methods of an aggregated * mock object. * @param array $methods Methods to be overridden * with mock versions. * @access public */ function generatePartial($methods) { if (! $this->_reflection->classExists($this->_class)) { return false; } $mock_reflection = new SimpleReflection($this->_mock_class); if ($mock_reflection->classExistsSansAutoload()) { trigger_error('Partial mock class [' . $this->_mock_class . '] already exists'); return false; } $code = $this->_extendClassCode($methods); return eval("$code return \$code;"); } /** * The new mock class code as a string. * @param array $methods Additional methods. * @return string Code for new mock class. * @access private */ function _createClassCode($methods) { $implements = ''; $interfaces = $this->_reflection->getInterfaces(); if (function_exists('spl_classes')) { $interfaces = array_diff($interfaces, array('Traversable')); } if (count($interfaces) > 0) { $implements = 'implements ' . implode(', ', $interfaces); } $code = "class " . $this->_mock_class . " extends " . $this->_mock_base . " $implements {\n"; $code .= " function " . $this->_mock_class . "() {\n"; $code .= " \$this->" . $this->_mock_base . "();\n"; $code .= " }\n"; if (in_array('__construct', $this->_reflection->getMethods())) { $code .= " " . $this->_reflection->getSignature('__construct') . " {\n"; $code .= " \$this->" . $this->_mock_base . "();\n"; $code .= " }\n"; } $code .= $this->_createHandlerCode($methods); $code .= "}\n"; return $code; } /** * The new mock class code as a string. The mock will * be a subclass of the original mocked class. * @param array $methods Additional methods. * @return string Code for new mock class. * @access private */ function _createSubclassCode($methods) { $code = "class " . $this->_mock_class . " extends " . $this->_class . " {\n"; $code .= " var \$_mock;\n"; $code .= $this->_addMethodList(array_merge($methods, $this->_reflection->getMethods())); $code .= "\n"; $code .= " function " . $this->_mock_class . "() {\n"; $code .= " \$this->_mock = &new " . $this->_mock_base . "();\n"; $code .= " \$this->_mock->disableExpectationNameChecks();\n"; $code .= " }\n"; $code .= $this->_chainMockReturns(); $code .= $this->_chainMockExpectations(); $code .= $this->_overrideMethods($this->_reflection->getMethods()); $code .= $this->_createNewMethodCode($methods); $code .= "}\n"; return $code; } /** * The extension class code as a string. The class * composites a mock object and chains mocked methods * to it. * @param array $methods Mocked methods. * @return string Code for a new class. * @access private */ function _extendClassCode($methods) { $code = "class " . $this->_mock_class . " extends " . $this->_class . " {\n"; $code .= " var \$_mock;\n"; $code .= $this->_addMethodList($methods); $code .= "\n"; $code .= " function " . $this->_mock_class . "() {\n"; $code .= " \$this->_mock = &new " . $this->_mock_base . "();\n"; $code .= " \$this->_mock->disableExpectationNameChecks();\n"; $code .= " }\n"; $code .= $this->_chainMockReturns(); $code .= $this->_chainMockExpectations(); $code .= $this->_overrideMethods($methods); $code .= "}\n"; return $code; } /** * Creates code within a class to generate replaced * methods. All methods call the _invoke() handler * with the method name and the arguments in an * array. * @param array $methods Additional methods. * @access private */ function _createHandlerCode($methods) { $code = ''; $methods = array_merge($methods, $this->_reflection->getMethods()); foreach ($methods as $method) { if ($this->_isConstructor($method)) { continue; } $mock_reflection = new SimpleReflection($this->_mock_base); if (in_array($method, $mock_reflection->getMethods())) { continue; } $code .= " " . $this->_reflection->getSignature($method) . " {\n"; $code .= " \$args = func_get_args();\n"; $code .= " \$result = &\$this->_invoke(\"$method\", \$args);\n"; $code .= " return \$result;\n"; $code .= " }\n"; } return $code; } /** * Creates code within a class to generate a new * methods. All methods call the _invoke() handler * on the internal mock with the method name and * the arguments in an array. * @param array $methods Additional methods. * @access private */ function _createNewMethodCode($methods) { $code = ''; foreach ($methods as $method) { if ($this->_isConstructor($method)) { continue; } $mock_reflection = new SimpleReflection($this->_mock_base); if (in_array($method, $mock_reflection->getMethods())) { continue; } $code .= " " . $this->_reflection->getSignature($method) . " {\n"; $code .= " \$args = func_get_args();\n"; $code .= " \$result = &\$this->_mock->_invoke(\"$method\", \$args);\n"; $code .= " return \$result;\n"; $code .= " }\n"; } return $code; } /** * Tests to see if a special PHP method is about to * be stubbed by mistake. * @param string $method Method name. * @return boolean True if special. * @access private */ function _isConstructor($method) { return in_array( strtolower($method), array('__construct', '__destruct')); } /** * Creates a list of mocked methods for error checking. * @param array $methods Mocked methods. * @return string Code for a method list. * @access private */ function _addMethodList($methods) { return " var \$_mocked_methods = array('" . implode("', '", array_map('strtolower', $methods)) . "');\n"; } /** * Creates code to abandon the expectation if not mocked. * @param string $alias Parameter name of method name. * @return string Code for bail out. * @access private */ function _bailOutIfNotMocked($alias) { $code = " if (! in_array(strtolower($alias), \$this->_mocked_methods)) {\n"; $code .= " trigger_error(\"Method [$alias] is not mocked\");\n"; $code .= " \$null = null;\n"; $code .= " return \$null;\n"; $code .= " }\n"; return $code; } /** * Creates source code for chaining to the composited * mock object. * @return string Code for mock set up. * @access private */ function _chainMockReturns() { $code = " function setReturnValue(\$method, \$value, \$args = false) {\n"; $code .= $this->_bailOutIfNotMocked("\$method"); $code .= " \$this->_mock->setReturnValue(\$method, \$value, \$args);\n"; $code .= " }\n"; $code .= " function setReturnValueAt(\$timing, \$method, \$value, \$args = false) {\n"; $code .= $this->_bailOutIfNotMocked("\$method"); $code .= " \$this->_mock->setReturnValueAt(\$timing, \$method, \$value, \$args);\n"; $code .= " }\n"; $code .= " function setReturnReference(\$method, &\$ref, \$args = false) {\n"; $code .= $this->_bailOutIfNotMocked("\$method"); $code .= " \$this->_mock->setReturnReference(\$method, \$ref, \$args);\n"; $code .= " }\n"; $code .= " function setReturnReferenceAt(\$timing, \$method, &\$ref, \$args = false) {\n"; $code .= $this->_bailOutIfNotMocked("\$method"); $code .= " \$this->_mock->setReturnReferenceAt(\$timing, \$method, \$ref, \$args);\n"; $code .= " }\n"; return $code; } /** * Creates source code for chaining to an aggregated * mock object. * @return string Code for expectations. * @access private */ function _chainMockExpectations() { $code = " function expect(\$method, \$args = false, \$msg = '%s') {\n"; $code .= $this->_bailOutIfNotMocked("\$method"); $code .= " \$this->_mock->expect(\$method, \$args, \$msg);\n"; $code .= " }\n"; $code .= " function expectArguments(\$method, \$args = false, \$msg = '%s') {\n"; $code .= $this->_bailOutIfNotMocked("\$method"); $code .= " \$this->_mock->expectArguments(\$method, \$args, \$msg);\n"; $code .= " }\n"; $code .= " function expectAt(\$timing, \$method, \$args = false, \$msg = '%s') {\n"; $code .= $this->_bailOutIfNotMocked("\$method"); $code .= " \$this->_mock->expectArgumentsAt(\$timing, \$method, \$args, \$msg);\n"; $code .= " }\n"; $code .= " function expectArgumentsAt(\$timing, \$method, \$args = false, \$msg = '%s') {\n"; $code .= $this->_bailOutIfNotMocked("\$method"); $code .= " \$this->_mock->expectArgumentsAt(\$timing, \$method, \$args, \$msg);\n"; $code .= " }\n"; $code .= " function expectCallCount(\$method, \$count) {\n"; $code .= $this->_bailOutIfNotMocked("\$method"); $code .= " \$this->_mock->expectCallCount(\$method, \$count, \$msg = '%s');\n"; $code .= " }\n"; $code .= " function expectMaximumCallCount(\$method, \$count, \$msg = '%s') {\n"; $code .= $this->_bailOutIfNotMocked("\$method"); $code .= " \$this->_mock->expectMaximumCallCount(\$method, \$count, \$msg = '%s');\n"; $code .= " }\n"; $code .= " function expectMinimumCallCount(\$method, \$count, \$msg = '%s') {\n"; $code .= $this->_bailOutIfNotMocked("\$method"); $code .= " \$this->_mock->expectMinimumCallCount(\$method, \$count, \$msg = '%s');\n"; $code .= " }\n"; $code .= " function expectNever(\$method) {\n"; $code .= $this->_bailOutIfNotMocked("\$method"); $code .= " \$this->_mock->expectNever(\$method);\n"; $code .= " }\n"; $code .= " function expectOnce(\$method, \$args = false, \$msg = '%s') {\n"; $code .= $this->_bailOutIfNotMocked("\$method"); $code .= " \$this->_mock->expectOnce(\$method, \$args, \$msg);\n"; $code .= " }\n"; $code .= " function expectAtLeastOnce(\$method, \$args = false, \$msg = '%s') {\n"; $code .= $this->_bailOutIfNotMocked("\$method"); $code .= " \$this->_mock->expectAtLeastOnce(\$method, \$args, \$msg);\n"; $code .= " }\n"; $code .= " function tally() {\n"; $code .= " }\n"; return $code; } /** * Creates source code to override a list of methods * with mock versions. * @param array $methods Methods to be overridden * with mock versions. * @return string Code for overridden chains. * @access private */ function _overrideMethods($methods) { $code = ""; foreach ($methods as $method) { if ($this->_isConstructor($method)) { continue; } $code .= " " . $this->_reflection->getSignature($method) . " {\n"; $code .= " \$args = func_get_args();\n"; $code .= " \$result = &\$this->_mock->_invoke(\"$method\", \$args);\n"; $code .= " return \$result;\n"; $code .= " }\n"; } return $code; }}?>
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?