使用模拟对象作为模拟函数的结果

时间:2014-02-25 11:04:59

标签: mocking phpunit

请考虑此功能

public static function load($ID, $iConnectionType=NULL)
{
    $oStatement = self::getLoadStatement($ID);
    if ($oStatement->rowCount() == 0) {
        throw new \ObjectNotFoundException($ID, 'Unable to load asset');
    }

    $oItem = self::loadFromStatement($oStatement);
    $oItem->setConnectionType($iConnectionType);

    return $oItem;
}

现在我想测试一下这个功能。

到目前为止我所拥有的是:

public function testLoad()
{
    $oMockedPDOStatement = $this->getMockBuilder('\PDOStatement')
        ->setMethods(array('rowCount'))
        ->getMock();
    $oMockedPDOStatement->expects($this->any())->method('rowCount')->will($this->returnValue(1));

    $mockedObject = $this->getMockBuilder('AssetFactory')
        ->setMethods(array('loadFromStatement', 'getLoadStatement'))
        ->getMock();
    $mockedObject::staticExpects($this->any())
        ->method('getLoadStatement')
        ->will($this->returnValue($oMockedPDOStatement));
    $mockedObject::staticExpects($this->any())
        ->method('loadFromStatement')
        ->will($this->returnValue(new TestAsset()));

    $this->assertInstanceOf('TestAsset', $mockedObject::load(5));
}

问题是运行此测试时出现以下故障

1)AssetFactoryTest :: testLoad ObjectNotFoundException:无法加载资产

我认为oMockedPDOStatement会照顾$oStatement->rowCount(),但显然不是这样。正确测试这个问题的解决方案是什么?

感谢。

1 个答案:

答案 0 :(得分:0)

您的问题是后期静态绑定(或您没有使用它)。为了对此进行测试,您的代码需要使用static而不是self。您的测试是调用实际方法而不是使用模拟方法。

http://sebastian-bergmann.de/archives/883-Stubbing-and-Mocking-Static-Methods.html

你的职能需要成为:

public static function load($ID, $iConnectionType=NULL)
{
    $oStatement = static::getLoadStatement($ID);
    if ($oStatement->rowCount() == 0) {
        throw new \ObjectNotFoundException($ID, 'Unable to load asset');
    }

    $oItem = static::loadFromStatement($oStatement);
    $oItem->setConnectionType($iConnectionType);

    return $oItem;
}