【问题标题】:PHPUnit - Mock PDO Statement fetchPHPUnit - 模拟 PDO 语句获取
【发布时间】:2011-07-19 17:40:01
【问题描述】:

仍在测试映射器类的过程中,我需要模拟 PDO。 但是现在我遇到了一个无限循环的问题:

$arrResult = array(
                    array('id'=>10, 'name'=>'abc'),
                    array('id'=>11, 'name'=>'def'),
                    array('id'=>12, 'name'=>'ghi')
                    );

$STMTstub->expects($this->any())
            ->method('fetch')
            ->will($this->returnValue($arrResult));
$PDOstub = $this->getMock('mockPDO');
    $PDOstub->expects($this->any())
            ->method('prepare')
            ->will($this->returnValue($STMTstub));

当然,在测试 1 fetch 或 fetchAll 时,该代码是完美的。但是当涉及到多次获取时,就会发生无限循环。就像在那种情况下:

while($arr = $stmt->fetch()){
    //...
}

所以我希望 fetch() 循环遍历所有 $arrResult 并一一返回子数组以模拟真正的 fetch() 行为。我可以“挂钩一个功能”吗?

【问题讨论】:

标签: mocking pdo phpunit fetch


【解决方案1】:

你有两个选择:

  1. 对于一些结果,您可以使用at() 对返回的值进行排序,或者
  2. 要获得更多结果,您可以使用returnCallback() 调用一个函数,该函数可在多次调用中产生所需结果。

使用at() 非常简单。您传入一个 PHPUnit 与调用匹配的索引,以选择要触发的期望。请注意,传递给 at() 的索引是对模拟的所有调用。如果$STMTstub 在对fetch() 的调用之间会收到其他模拟调用,则需要相应地调整索引。

$STMTstub->expects($this->at(0))
          ->method('fetch')
          ->will($this->returnValue($arrResult[0]));
$STMTstub->expects($this->at(1))
          ->method('fetch')
          ->will($this->returnValue($arrResult[1]));
$STMTstub->expects($this->at(2))
          ->method('fetch')
          ->will($this->returnValue($arrResult[2]));

使用returnCallback() 需要更多的脚手架,但它避免了所有的索引恶作剧。 ;)

public static function yieldResults($name, $results) {
    static $indexes = array();
    if (isset($indexes[$name])) {
        $index = $indexes[$name] + 1;
    }
    else {
        $index = 0;
    }
    self::assertLessThan(count($results), $index);
    $indexes[$name] = $index;
    return $results[$index];
}

public function testMyPdo() {
    $STMTmock = ...
    $STMTmock->expects($this->any())->method('fetch')
             ->will($this->returnCallback(function() {
                 return self::yieldResults('testMyPdo', 
                     array(
                         array('id'=>10, 'name'=>'abc'),
                         array('id'=>11, 'name'=>'def'),
                         array('id'=>12, 'name'=>'ghi'),
                     );});
}

yieldResults() 是通用的,只要您为每个结果集指定一个唯一的$name,它就可以同时处理任意数量的结果集。如果您没有使用带有回调的 PHP 5.3,请将对 yieldResults() 的调用封装在另一个您传递给 returnCallback() 的函数中。我还没有测试过,但它看起来还不错。

【讨论】:

  • 不允许我编辑因为 6 个字符,但函数定义应该是“yieldResults”而不是“yieldNthResult”
猜你喜欢
  • 2011-07-17
  • 1970-01-01
  • 2015-11-01
  • 2021-04-09
  • 2011-03-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多