2010-08-26 2 views
11

Sto provando a scrivere un test unitario con phpunit per un modello che usa la dottrina 2. Voglio prendere in giro le entità dottrinali ma in realtà non ho idea di come farlo. Qualcuno può spiegarmi come devo fare questo? Sto usando Zend Framework.Come creare un oggetto fittizio di un'entità dottrina?

Il modello che deve essere testato

class Country extends App_Model 
{ 
    public function findById($id) 
    { 
     try { 
      return $this->_em->find('Entities\Country', $id); 
     } catch (\Doctrine\ORM\ORMException $e) { 
      return NULL; 
     } 
    } 

    public function findByIso($iso) 
    { 
     try { 
      return $this->_em->getRepository('Entities\Country')->findOneByIso($iso); 
     } catch (\Doctrine\ORM\ORMException $e) { 
      return NULL; 
     } 
    } 
} 

bootstrap.php

protected function _initDoctrine() 
{ 
    Some configuration of doctrine 
    ... 
    // Create EntityManager 
    $em = EntityManager::create($connectionOptions, $dcConf); 
    Zend_Registry::set('EntityManager', $em); 
} 

modello esteso

class App_Model 
{ 
    // Doctrine 2.0 entity manager 
    protected $_em; 

    public function __construct() 
    { 
     $this->_em = Zend_Registry::get('EntityManager'); 
    } 
} 

risposta

8

Doctrine 2 Le entità devono essere trattate come qualsiasi vecchia classe. Puoi prenderli in giro come qualsiasi altro oggetto in PHPUnit.

$mockCountry = $this->getMock('Country'); 

Al PHPUnit 5.4, il metodo getMock() è stato depricated. Utilizzare invece createMock() o getMockbuilder().

Come ha notato @beberlei, si sta utilizzando EntityManager all'interno della classe Entity stessa, che crea un numero di problemi persistenti e sconfigge uno degli scopi principali di Doctrine 2, ovvero che le Entità non sono interessate al proprio persistenza. Questi metodi "trova" appartengono davvero a repository class.

+0

Con il tuo codice, il Paese modello verrà deriso? Invece del Paese di entità. – tom

+0

In Doctrine 2 non esiste alcun concetto di "modello". Quali dottrine considerano Entità, altri quadri possono essere considerati come Modelli. Oppure, mi piace spesso fare riferimento al "livello del modello" che consiste in Entità e altre classi (convalide, servizi, ecc.) Che comprendono l'intero modello di dati. –

+0

Thx, per il tuo commento! Ho ora. – tom

1

Puoi mostrare come si inietta $ this -> _ em in "Paese"? Sembra che tu abbia unito le responsabilità qui iniettando l'EM in un'Entità. Ciò danneggia molto la testabilità. Idealmente nei tuoi modelli avresti una logica di business che ha passato le sue dipendenze, così che non hai bisogno del riferimento di EntityManager.

+0

Ciao, ho aggiornato il mio post. Su come inizializzo il gestore di entità. – tom

15

Ho le seguenti funzioni di setUp e teardown per i miei test di unità che usano Doctrine. Ti dà la possibilità di effettuare chiamate dottrina, senza in realtà toccare il DB:

public function setUp() 
{ 
    $this->em = $this->getMock('EntityManager', array('persist', 'flush')); 
    $this->em 
     ->expects($this->any()) 
     ->method('persist') 
     ->will($this->returnValue(true)); 
    $this->em 
     ->expects($this->any()) 
     ->method('flush') 
     ->will($this->returnValue(true)); 
    $this->doctrine = $this->getMock('Doctrine', array('getEntityManager')); 
    $this->doctrine 
     ->expects($this->any()) 
     ->method('getEntityManager') 
     ->will($this->returnValue($this->em)); 
} 

public function tearDown() 
{ 
    $this->doctrine = null; 
    $this->em  = null; 
} 

È quindi possibile utilizzare $this->doctrine (o anche) $this->em quando necessario. Dovrai aggiungere più definizioni di metodo se vuoi utilizzare remove o getRepository.

+1

Questo sta creando un nuovo oggetto EntityManager che sa solo come persistere e svuotare all'interno della classe di test. Credo che quello che l'OP sta chiedendo sia di prendere in giro i metodi persist e flush di un oggetto già esistente all'interno del suo ServiceManager. Quindi il suo codice di servizio contiene persist() e flush() e sta toccando il DB quando è solo un test. –