2014-09-16 2 views
2

Я добавляю модульные тесты к существующему проекту, который использует пространства имен. Мне раньше не приходилось использовать пространства имен, поэтому это приключение. Моя проблема в том, что в моих модульных тестах кажется, что издеваются методы, которые все еще вызываются. Ниже приведен пример файла кода и теста.PHPUnit и пространства имен - издевательские методы, все еще называемые

private function selectFromDb($fields, $criteria = null) { 
    $fields = is_array($fields) ? implode(', ', $fields) : $fields; 

    $sql = "SELECT $fields FROM balloons"; 

    if(!is_null($criteria)) { 
     $sql .= " WHERE $criteria"; 
    } 

    $adapter = $this->getAdapter(); 
    $statement = $adapter->query($sql); 
    $result = $statement->execute(); 

    return $result; 
} 

Вот код теста:

// I'm passing in data here which isn't consequential for the question. 
public function testSelectFromDb($fields, $criteria, $expectedSql) { 
    $statement = $this->getMockBuilder('Zend\Db\Adapter\Driver\Pdo\Statement') 
     ->disableOriginalConstructor() 
     ->setMethods(array('execute'))->getMock(); 
    $statement->expects($this->once()) 
     ->method('execute')->will($this->returnValue('fake')); 

    $adapter = $this->getMockBuilder('Zend\Db\Adapter\Adapter') 
     ->disableOriginalConstructor() 
     ->setMethods(array('query'))->getMock(); 
    $adapter->expects($this->once()) 
     ->method('query')->with($expectedSql) 
     ->will($this->returnValue($statement)); 

    $bm = $this->getMockBuilder('Application\Model\BalloonModel') 
     ->setMethods(array('getAdapter')) 
     ->disableOriginalConstructor()->getMock(); 
    $bm->expects($this->once()) 
     ->method('getAdapter')->will($this->returnValue($adapter)); 

    // I use reflection as the method is private to the class 
    $reflection = new ReflectionClass($bm); 
    $method = $reflection->getMethod('selectFromDb'); 
    $method->setAccessible(true); 

    $result = $method->invokeArgs($bm, array($fields, $criteria)); 

} 

На данный момент, я просто пытаюсь получить тест, чтобы выполнить до конца, но я по-прежнему получаю следующее сообщение об ошибке:

Tests\Model\BalloonModelTest::testSelectFromDb with data set "singleField" ('id', NULL, 'SELECT id FROM balloon') 
    Zend\Db\Adapter\Exception\InvalidQueryException: Statement could not be executed 

/apath/PHP/vendor/zendframework/zendframework/library/zend/db/adapter/driver/pdo/statement.php:245 
/apath/PHP/vendor/zendframework/zendframework/library/zend/db/adapter/driver/pdo/statement.php:240 
/apath/PHP/module/Application/src/application/model/balloonmodel.php:243 
/apath/PHP/tests/Model/BalloonModelTest.php:70 

Caused by 
PDOException: SQLSTATE[42S22]: Column not found: 1054 Unknown column 'id' in 'field list' 

/apath/PHP/vendor/zendframework/zendframework/library/zend/db/adapter/driver/pdo/statement.php:240 
/apath/PHP/module/Application/src/application/model/balloonmodel.php:243 
/apath/PHP/tests/Model/BalloonModelTest.php:70 

Это говорит мне, что вызовы 'getAdapter', 'query' и 'execute' все еще выполняются, хотя все они теоретически издеваются. Я проверял как можно лучше, что используемые имена классов используют правильные пространства имен. Есть идеи?

ответ

0

Проблема не в пространствах имен. Вероятно, вы пытаетесь издеваться над самим классом, и я предполагаю, что getAdapter() - это частный метод, вызываемый из класса.

Помните, что макет - это объект сгенерированного класса, который расширяет исходный класс.

Теперь есть Mock_XYZ extends BalloonModel, который добавляет фиктивный метод getAdapter(), но если метод getAdapter() в BalloonModel сама является частным, оно не будет отменено, но вы в конечном итоге с двумя различными способами (один внутренний и один внешний, если вы будете).

Решение

Рефакторинг кода использовать Dependency Injection. Я не говорю о контейнерах IoC, просто о создании других объектов, которые не относятся к самому классу, но вставляем их сеттерами или конструкторами. Затем вы можете сделать следующее после создания $adapter макета, а не насмешки getAdapter():

$bm->setAdapter($adapter); 
Смежные вопросы