是否可以在程序(非oo)函数上使用模拟?

时间:2012-10-24 13:27:36

标签: php unit-testing mocking phpunit

  

可能重复:
  PHP - override existing function

我想使用mocking对我的一些具有外部依赖性的函数进行单元测试。

所以这里......以下是我正在使用的简化模型。我继承的很多代码都是以这种方式编写的,所以我希望能够编写一些简单的测试而不必在可能的情况下重写:

function display_tasks($id)
{
    $tasks = call_some_function_that_runs_a_database_query($id);

    $html = "<some html>";

    foreach ($tasks as $task)
    {
        // Some operations here
    }

    $html .= "</some html>";

    return $html;
}

我的函数调用的代码没有包含在对象中,因此我无法将各种示例付诸实践,因为互联网上99%的示例都是基于面向对象的代码。甚至可以直接从PHPunit模拟过程函数吗?

我希望能够模拟出call_some_function_that_runs_a_database_query正在返回的内容。我已经开始使用内置的PHPunit模拟方法,但这样做并不会覆盖我函数中原始调用的结果。

非常感谢任何帮助或示例。

1 个答案:

答案 0 :(得分:3)

您可以使用runkit PHP extension替换一个功能,该功能将在测试期间返回您想要的功能。它比模拟对象更麻烦,因为在所有情况下(传递,失败,错误),你必须小心地将测试后的原始文件交换回来。

受测试的功能

function getTasksFromDatabase($id) {
    // call to database...
}

测试用例

function stub_getTasksFromDatabase($id) {
    return array('one', 'two', 'three');
}

class getUserTest extends PHPUnit_Framework_TestCase {
    public static function setUpBeforeClass() {
        runkit_function_rename('getTasksFromDatabase', 'orig_getTasksFromDatabase');
        runkit_function_rename('stub_getTasksFromDatabase', 'getTasksFromDatabase');
    }

    public function tearDownAfterClass() {
        runkit_function_rename('getTasksFromDatabase', 'stub_getTasksFromDatabase');
        runkit_function_rename('orig_getTasksFromDatabase', 'getTasksFromDatabase');
    }

    public function setUp() {
        $html = getTasks(1);
        self::assertEquals('<some html>...one...two...three...</some html>', $html);
    }
}