断言函数被调用

时间:2012-05-17 11:32:30

标签: php phpunit

使用phpunit进行测试时,我想断言一个函数调用:

给出一个类:

Class TimeWrapper {
  public function time() {
    return time();
  }
}

其单位测试:

Class TimeWrapperTest extends PHPUnit_FrameworkTestCase {
  public function testTime() {
    //Pseudocode as example of a possible solution:
    $this->assertCallsFunction("time");
  }
}

我特意寻找一种测试全局函数调用的方法。

FWIW:使用rspec,我使用Message Expectations。我希望在PHPUnit中实现类似或类似的东西。

2 个答案:

答案 0 :(得分:0)

不确定是否已经为此目的做了一些事情。

但是如果你想亲自实现它,你可以看看xdebug code coverage

答案 1 :(得分:0)

如果目标是验证TimeWrapper是否调用内置PHP函数time,则需要使用runkit扩展名。这将允许您使用您自己的版本替换内置函数来记录调用。您需要在runkit.internal_override中启用php.ini设置,以便重命名内部功能。

class TimeWrapperTest extends PHPUnit_Framework_TestCase {
    static $calledTime;

    function setUp() {
        self::$calledTime = false;
    }

    function testTimeGetsCalled() {
        $fixture = new TimeWrapper;
        try {
            runkit_function_rename('time', 'old_time');
            runkit_function_rename('new_time', 'time');
            $time = $fixture->time();
            self::assertTrue('Called time()', $calledTime);
        }
        catch (Exception $e) {
            // PHP lacks finally, but must make sure to revert time() for other test
        }
        runkit_function_rename('time', 'new_time');
        runkit_function_rename('old_time', 'time');
        if ($e) throw $e;
    }
}

function new_time() {
    TimeWrapperTest::$calledTime = true;
    return old_time();
}

如果你不能使用扩展或只是想避免这种欺骗,你可以修改TimeWrapper以允许你覆盖在运行时调用的函数。

class TimeWrapper {
    private $function;

    public function __construct($function = 'time') {
        $this->function = $function;
    }

    public function time() {
        return call_user_func($this->function);
    }
}

使用上面的测试用例而不调用runkit_function_rename并将new_time传递给TimeWrapper构造函数。这里的缺点是,每次拨打TimeWrapper::time时,您都会在生产中支付(可能很小的)性能损失。