2011-03-17 21 views
8

hazırladı. Ben anlamda, kolay mapper sınıfta enjekte edilecek PDO örneğinin alay edebilir, ama PDO sınıfı tarafından Oluşturulan olarak, PreparedStatement sınıf alay anlamaya olamaz. Benim durumumdaPHPUnit - alay Nasıl PDO ben PHPUnit ile bir haritacı sınıfını test etmek birimine çalışıyorum deyimi

ben PDO sınıfını uzattığımızı, bu yüzden bu var:

public function __construct($dsn, $user, $pass, $driverOptions) 
{ 

    //... 

    parent::__construct($dsn, $user, $pass, $driverOptions); 
    $this->setAttribute(PDO::ATTR_STATEMENT_CLASS, 
     array('Core_Db_Driver_PDOStatement', array($this))); 
} 

noktası Core_Db_Driver_PDOStatement PDO Class yapıcısı enjekte olmadığını, bu statik instanciated oluyor. Ve bunu da olsa:

public function __construct($dsn, $user, $pass, $driverOptions, $stmtClass = 'Core_Db_Driver_PDOStatement') 
{ 

    //... 

    parent::__construct($dsn, $user, $pass, $driverOptions); 
    $this->setAttribute(PDO::ATTR_STATEMENT_CLASS, 
     array($stmtClass, array($this))); 
} 

... ben Hazırlanan deyimi sınıfının kendi alay örneğini geçemez gibi statik instanciation hâlâ burada.

Herhangi bir fikrin var mı?

Düzenleme: Çözüm, anwser uyarlanmıştır:

/** 
* @codeCoverageIgnore 
*/ 
private function getDbStub($result) 
{ 
    $STMTstub = $this->getMock('PDOStatement'); 
    $STMTstub->expects($this->any()) 
      ->method('fetchAll') 
      ->will($this->returnValue($result)); 


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

    return $PDOstub; 
} 

public function testGetFooById() 
{ 
    $arrResult = array(...); 
    $PDOstub = $this->getDbStub($arrResult); 
} 

cevap

10

PDO sınıfı sadece pdo sınıfını dışarı alay alay edebilir ve tüm bu bağımlılıkları buysa. Girişleri ve çıktıları atasözleri aracılığıyla tanımladığınızdan dolayı, pdo sınıfının deyim sınıfını veya yapıcısını önemsemeye gerek yoktur.

Yani sahte bir nesnesi döndüren bir sahte nesne gerekiyor.

Biraz kafa karıştırıcı görünebilir ama sadece test altında sınıf ne yaptığını test etmelidir ve başka bir şey hemen hemen DB bağlantısı tüm diğer bölümleri ile deplasmanda yapabilirsiniz beri.

Bu örnekte sen anlamaya istediğim şey:

  • denilen hazırlamak mı?
  • fetchAll döner hazırlamak ne denir mi?
  • Bu aramanın sonucu döndü mü?

Eğer öyleyse: Tüm iyi. Eğer fetchAll Eğer testte karar verebilir şey dönecektir edebilirsiniz sahte olduğunu ne zaman Bildirimi enjekte etmek gerek:

<?php 
class myClass { 
    public function __construct(ThePDOObject $pdo) { 
     $this->db = $pdo; 
    } 

    public function doStuff() { 
     $x = $this->db->prepare("..."); 
     return $x->fetchAll(); 
    } 
} 

class myClassTest extends PHPUnit_Framework_TestCase { 

    public function testDoStuff() { 

     $fetchAllMock = $this 
      ->getMockBuilder("stdClass" /* or whatever has a fetchAll */) 
      ->setMethods(array("fetchAll")) 
      ->getMock(); 
     $fetchAllMock 
      ->expects($this->once())->method("fetchAll") 
      ->will($this->returnValue("hello!")); 

     $mock = $this 
      ->getMockBuilder("ThePDOObject") 
      ->disableOriginalConstructor() 
      ->setMethods(array("prepare")) 
      ->getMock(); 
     $mock 
      ->expects($this->once()) 
      ->method("prepare") 
      ->with("...") 
      ->will($this->returnValue($fetchAllMock)); 

     $x = new myClass($mock); 
     $this->assertSame("hello!", $x->doStuff()); 


    } 

} 
+0

Kesinlikle, ben de iyi anlaşılmamış vermedi parçasını buldunuz. Benim uyarlanmış çözümüme yer vermek için sorumu düzenledim. Teşekkürler ! – FMaz008

+1

Bu yaklaşımdaki sorun, uygulama kodu uygulamasını teste tabi tutmasıdır. Test, uygulamanın çağırılıp çağrılmadığını bilmeli -> fetch() veya fetchAll()? Bir şey değil! Kod fetchaAll() yerine fetch() kullanılacak şekilde uyarlanmışsa, yöntem yine de doğru şekilde çalışmayabilir, ancak sınama başarısız olur. –

+1

@TomB, bu sadece bu cevapla değil, alay bağımlılıkları ile ilgili genel bir sorundur. – PeerBr