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 + -
显示快捷键?