2015-01-21 3 views
5

Desidero utilizzare Prophecy ("phppec/prophecy-phpunit") per la prima volta per creare test di unità per le mie classi. Voglio testare una funzione che chiama un'altra funzione nello stesso servizio, ecco il codice:Come prendere in giro un metodo dalla classe che si sta testando con Prophecy?

class UserManager 
{ 
    private $em; 
    private $passwordHelper; 

    public function __construct(\Doctrine\ORM\EntityManager $em, \MainBundle\Helper\PasswordHelper $passwordHelper) 
    { 
     $this->em = $em; 
     $this->passwordHelper = $passwordHelper; 
    } 

    public function getUserForLdapLogin($ldapUser) 
    { 
      $dbUser = $this 
       ->em 
       ->getRepository('MainBundle:User') 
       ->findOneBy(array('username' => $ldapUser->getUsername())); 

     return (!$dbUser) ? 
       $this->createUserFromLdap($ldapUser) : 
       $this->updateUserFromLdap($ldapUser, $dbUser); 
    } 

primo problema che ho avuto è stata che mi stava usando findOneByUsername e profezia, per quanto riguarda la mia conoscenza va, non si consente per: simulare metodi magici (_call per EntityRepository), metodi fittizi che non esistono, prendere in giro la classe che si sta testando. Se questi sono veri, sono un po 'sottaceto, ovvero non posso testare questa funzione senza testare le altre funzioni della classe.

Finora, la mia prova assomiglia a questo:

class UserManagerTest extends \Prophecy\PhpUnit\ProphecyTestCase 
{ 

     public function testGetUserForLdapLoginWithNoUser() 
     { 
      $ldapUser = new LdapUser(); 
      $ldapUser->setUsername('username'); 

      $em = $this->prophesize('Doctrine\ORM\EntityManager'); 
      $passwordHelper = $this->prophesize('MainBundle\Helper\PasswordHelper'); 

      $repository = $this->prophesize('Doctrine\ORM\EntityRepository'); 
      $em->getRepository('MainBundle:User')->willReturn($repository); 
      $repository->findOneBy(array('username' => 'username'))->willReturn(null); 

      $em->getRepository('MainBundle:User')->shouldBeCalled(); 
      $repository->findOneBy(array('username' => 'username'))->shouldBeCalled(); 

      $service = $this->prophesize('MainBundle\Helper\UserManager') 
      ->willBeConstructedWith(array($em->reveal(), $passwordHelper->reveal())); 

      $service->reveal(); 
      $service->getUserForLdapLogin($ldapUser); 
    } 
} 

E, naturalmente, i test falliscono perché le promesse su $em, e il repository non sono soddisfatte. Se istanziato la classe che sto testando, i test falliscono perché la funzione chiama quindi sulla stessa classe e non è testata.

Qualche suggerimento?

+0

Non l'ho mai usato, quindi non posso aiutare me stesso.Tuttavia, se si è ancora bloccato in un paio di giorni (vale a dire quando una taglia questione può essere applicata), mi ping con @halfer e io aggiungerne uno. Buona domanda! – halfer

+0

risposta migliore che ho trovato finora è che la classe probabilmente non seguire i principi S.O.L.I.D e non ha una sola responsabilità. Quindi fai in modo che la tua classe sia dritta prima di provare a usare la profezia. – anegrea

risposta

0

Primo problema:

Non usare la magia, la magia è male. __call può portare a comportamenti imprevedibili.

"le promesse di $ em, e il repository non sono soddisfatte":

Non rendere il codice dipendono classe ma Interface. Quindi prendi in giro l'interfaccia anziché la classe! Dovresti prendere in giro ObjectManager invece di EntityManager. (Non dimenticate di cambiare il tipo di parametri)

E l'ultimo punto:

Prima di rivelare.

$service->createUserFromLdap() 
    ->shouldBeCalled() 
    ->willReturn(null); 
0

Per quanto riguarda il problema di non essere in grado di prendere in giro i metodi che non esistono, è possibile utilizzare

http://docs.mockery.io/en/latest/

al posto della profezia. La presa in giro ti permette di fare proprio questo. A rigor di termini, ciò infrange alcune delle regole del buon design, ma d'altra parte, a volte è solo molto utile. Ad ogni modo, la presa in giro è molto simile, per quanto riguarda le caratteristiche, ed è altrettanto intuitiva e facile da usare. Tuttavia, non hanno ancora rilasciato la versione stabile, quindi tieni presente che se decidi di usarlo.

Qui è possibile trovare un buon confronto di due librerie

http://everzet.com/post/72910908762/conceptual-difference-between-mockery-and-prophecy