PHPUnit - выборка ложного оператора PDO - PullRequest
1 голос
/ 21 марта 2011

Все еще в процессе тестирования класса картографа, мне нужно смоделировать 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 выборки или выборки Все.Но когда дело доходит до множественной выборки, происходит бесконечный цикл.Как в этом случае:

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

Так что я бы хотел, чтобы fetch () перебирала все $ arrResult и возвращала подмассив один за другим для имитации истинного поведения fetch ().Могу ли я "подключить функцию", чтобы сделать это или что-то?

1 Ответ

4 голосов
/ 21 марта 2011

У вас есть два варианта:

  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(). Я не проверял это, но это кажется довольно здравым.

...