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은 원래 클래스를 확장하는 생성 된 클래스의 객체라는 것을 기억하십시오.

이제, 모의 방법 getAdapter()을 추가 Mock_XYZ extends BalloonModel이, 그러나 BalloonModel에서 getAdapter() 방법 자체가 개인 인 경우, 그것은 무시되지 않습니다하지만 당신은 두 가지 방법 (내부 하나 만약에 당신 외부의 하나)와 끝까지.

솔루션

는 의존성 삽입 (Dependency Injection)를 사용하도록 코드를 리팩토링. 나는 IoC 컨테이너에 대해 이야기하는 것이 아니라 클래스 자체가 아닌 다른 객체를 만드는 것에 관한 것이 아니라 setter 또는 생성자를 주입하는 것입니다. 그런 다음 $adapter 모의를 작성한 후 getAdapter() 대신 getAdapter()을 작성하면 다음을 수행 할 수 있습니다.

$bm->setAdapter($adapter); 
관련 문제