Zend FR

Consultez la FAQ sur le ZF avant de poster une question

Vous n'êtes pas identifié.

#1 17-04-2014 12:10:07

JGreco
Administrateur
Date d'inscription: 22-12-2012
Messages: 432

Tests unitaire avec doctrine, compréhension, appréhension

Bonjour à tous !

Histoire de me changer les idée par rapport aux acl j'ai décidé de me lancer dans l'adaptation de mon projets aux tests unitaires de ma couche Service. J'utilise Jenkins pour centraliser et afficher le coverage des tests (ainsi que d'autre choses), je centralise le lancement de mes test a la racine mais j'ai un bootstrap.php ainsi qu'un fichier de config dans chaque dossier tests de chaque module.

Je récupère mon entity manager dans mes classes de test via cette méthode  déclarée dans le fichier bootstrap et appelée dans le setUp()

Code:

        $this->sm = AlbumBootstrap::getServiceManager();
        $this->em = $this->sm->get('doctrine.entitymanager.orm_default');

Je travail sur le getting started Album pour l'instant afin de placer les concepts à mon projet.

Bon maintenant que tout est plus ou moins placé ( si vous avez des question n'hésitez pas) je vous explique le soucis.

J'apprend a faire des mocks actuellement (quand j'apprends pas zf2 ou doctrine lol) j'ai lu beaucoup à propos d'eux.
Dans mon cas, j'aimerai tester, pour commencer, à vérifier que je récupère bien tous mes albums dans la table sous forme de tableau.(cela peut paraitre inutile mais c'est pour comprendre dans un premier temps)
En suivant ce que Orkin m'avait conseillé comme architecture (DAO, Service, Entity etc...) je remarque que quand je fais :

Code:

[lang=php]
public function testCanFetchAllAlbum()
    {
        $resultSet = array();
        $this->mockAlbumService = $this->getMock('Album\Service\AlbumService');

        /**
         * On attend à ce que le système n'appelle fetchAll qu'une seule fois sinon erreur.
         * Test utile dans le cas de suppression. Ou mise à jour.
         */
        $this->mockAlbumService->expects($this->once())->method('fetchAll')->will($this->returnValue(array()));

        var_dump($this->em->getRepository('Album\Service\AlbumService'));exit();
        $Album = $this->em->getRepository('Album\Service\AlbumService');
        $this->assertInstanceOf('Album\Service\AlbumService', $Album);

        $this->assertSame($resultSet, $Album->fetchAll());

    }

Il me met cette erreur :

Code:

1) AlbumTest\Entity\AlbumEntityTest::testCanFetchAllAlbum
Doctrine\Common\Persistence\Mapping\MappingException: The class 'Album\Service\AlbumService' was not found in the chain configured namespaces Application\Entity, Album\Entity

Je comprend donc que seul le namespace Application\Entity ou Album\Entity est déclaré et utilisable, mon namespace Album\Service ne l'est pas.
Comment cela se fait ? Comment je peux y remédier ?

Merci pour votre temps et explications.


ZF2 et doctrine addict
profil stack overflow : http://stackoverflow.com/users/3333246/ … ab=profile

Hors ligne

 

#2 17-04-2014 14:27:49

JGreco
Administrateur
Date d'inscription: 22-12-2012
Messages: 432

Re: Tests unitaire avec doctrine, compréhension, appréhension

J'ai avancé un peu sur ce problème, je crois que c'est parce que je ne déclare pas Album\Service\[mes services] comme faisant partie des namespaces accordés à doctrine pour effectuer des traitements.

Cela viendrait donc de ceci :

Code:

[lang=php]
'doctrine' => array(
        'driver' => array(
            'album_entity' => array(
                'class' => 'Doctrine\ORM\Mapping\Driver\AnnotationDriver',
                'paths' => __DIR__ . '/../src/'.__NAMESPACE__.'/Entity',
            ),
            'orm_default' => array(
                'drivers' => array(
                    __NAMESPACE__.'\Entity' => 'album_entity',
                )
            )
        )
    ),

J'ai essayé d'y rajouter le namespace Service mais si je le fait il me renvoi l'erreur :

Code:

1) AlbumTest\Entity\AlbumEntityTest::testCanFetchAllAlbum
Doctrine\ORM\Mapping\MappingException: Class "Album\Service\AlbumService" is not a valid entity or mapped super class.

La je suis perdu y a t'il une classe doctrine qui permet de régler ce point là ?


ZF2 et doctrine addict
profil stack overflow : http://stackoverflow.com/users/3333246/ … ab=profile

Hors ligne

 

#3 17-04-2014 14:32:43

Orkin
Administrateur
Lieu: Paris
Date d'inscription: 09-12-2011
Messages: 1261

Re: Tests unitaire avec doctrine, compréhension, appréhension

Le problème vient de là :

JGreco a écrit:

Code:

[lang=php]$this->em->getRepository('Album\Service\AlbumService');

Hors ligne

 

#4 17-04-2014 14:38:18

JGreco
Administrateur
Date d'inscription: 22-12-2012
Messages: 432

Re: Tests unitaire avec doctrine, compréhension, appréhension

Peut tu m'en dire plus, s'il te plait ? je ne voit pas.


ZF2 et doctrine addict
profil stack overflow : http://stackoverflow.com/users/3333246/ … ab=profile

Hors ligne

 

#5 17-04-2014 14:39:05

Orkin
Administrateur
Lieu: Paris
Date d'inscription: 09-12-2011
Messages: 1261

Re: Tests unitaire avec doctrine, compréhension, appréhension

Tu cherches le repository d'un service donc ça ne peut pas marcher. C'est une entité qu'il faut mettre.

Hors ligne

 

#6 17-04-2014 14:42:33

JGreco
Administrateur
Date d'inscription: 22-12-2012
Messages: 432

Re: Tests unitaire avec doctrine, compréhension, appréhension

Oui comme je l'ai expliqué c'est dans la couche service que je fais mes traitements. fetchAll par exemple. Je dois mettre Album\Entity\Album et comment je lance ma methode fetch all pour la comparer a mon mock fetchAll ?

Je fait peut être une erreur de conception... mais une explication de pourquoi je fais une erreur me permettrait de comprendre.

Merci en tous cas :p


ZF2 et doctrine addict
profil stack overflow : http://stackoverflow.com/users/3333246/ … ab=profile

Hors ligne

 

#7 17-04-2014 14:49:38

Orkin
Administrateur
Lieu: Paris
Date d'inscription: 09-12-2011
Messages: 1261

Re: Tests unitaire avec doctrine, compréhension, appréhension

Bah le service va avoir la méthode getAll par exemple (pour pas te mélanger) et dans cette méthode tu vas appeler l'entity manager pour faire un findAll(). C'est ce que je te disais le service a accès à l'entité mais l'entité ne connait pas le service.

Là tu demandes à l'entity manager (donc la couche DAO) d'utiliser un service (donc la couche Service) hors c'est la couche service qui doit appeler la couche DAO.

Hors ligne

 

#8 17-04-2014 15:13:13

JGreco
Administrateur
Date d'inscription: 22-12-2012
Messages: 432

Re: Tests unitaire avec doctrine, compréhension, appréhension

Oui je comprends, ma classe AlbumService possède une méthode fetchAll sauf que quand j'y accede via mes test il me récupère pas l'entity manager

Code:

    public function fetchAll()
    {
        $this->em = $this->getServiceManager()->get('doctrine.entitymanager.orm_default');
        $connect = $this->em->getConnection();
        $albums = $connect->fetchAll('SELECT * FROM Album');
        //controle ici si vide ?
        return $albums;
    }

Donc du coup je suis perdu.


ZF2 et doctrine addict
profil stack overflow : http://stackoverflow.com/users/3333246/ … ab=profile

Hors ligne

 

#9 17-04-2014 15:21:52

Orkin
Administrateur
Lieu: Paris
Date d'inscription: 09-12-2011
Messages: 1261

Re: Tests unitaire avec doctrine, compréhension, appréhension

Ta méthode fetchAll() n'est vraiment pas bonne ^^.

Il faut mocker l'entity manager. Ton soucis j'ai l'impression c'est que tu veux tout apprendre en même temps et au final tu apprends (heureusement) mais trop de trucs en même temps. Concentres toi sur d'abord bien maîtriser le framework avec doctrine avant de vouloir mettre en place une plateforme d'intégration continue avec Jenkins.

Donc dans ton cas :

Code:

[lang=php]
$this->em = $this->getServiceManager()->get('doctrine.entitymanager.orm_default');
return $this->em->getRepository('Album\Entity\Album')->findAll(); // Le findAll fait la requête tout seul du select * from Album

Hors ligne

 

#10 17-04-2014 22:56:51

JGreco
Administrateur
Date d'inscription: 22-12-2012
Messages: 432

Re: Tests unitaire avec doctrine, compréhension, appréhension

Salut, merci pour ta réponse,
J'apprends tout en même temps car j'ai pas forcément le choix je dois le faire et j'arrive a retrouver mes petits, je me débloque un peu tous les jours et j'apprends tous les jours ^^. Je suis confiant pour la suite mais c'est vrai que certaines chose m’échappent dans ce cas la je cherche et si je voit pas je demande.

Je test ta solution demain, et je pense en effet que tu as raison ! cela devrait marcher !


ZF2 et doctrine addict
profil stack overflow : http://stackoverflow.com/users/3333246/ … ab=profile

Hors ligne

 

#11 18-04-2014 13:08:28

JGreco
Administrateur
Date d'inscription: 22-12-2012
Messages: 432

Re: Tests unitaire avec doctrine, compréhension, appréhension

Bonjour Orkin,
Merci déjà pour ta réponse :

Code:

 $Album = $this->em->getRepository('Album\Entity\Album')->findAll();

Me récupère bien les albums en base de donnée sous forme d'array. Ceci m'a permit de comprendre qu'en réalité l'entité Album est directement lié via l'entity Manager à la base de donnée et qu'il n'y à pas besoin de récupérer les données depuis la couche service, c'est bien cela ?

Mais je crois pas avoir saisi encore comment comparer cet array pour effectuer mon test. Si je voulais faire une assertion sur le fait que le tableau ne soit pas vide ce serait bon je ferai un assertNotEmpty ou un assertNotNull ou que sais-je encore.

Mais ai-je moyen de comparer un

Code:

$Album = $this->em->getRepository('Album\Entity\Album')->findAll();

Avec une méthode de ma couche service (fetchAll) qui doit me retourner la même chose ?

Code:

$this->mockAlbumService->expects($this->once())->method('fetchAll')->returnValue('on met quoi ici ?'); //retourne un truc a comparer avec findAll ?

Cet exemple me sert juste a comprendre le principe, sur le fond comparer des select * c'est inutile dans un projet ou j'aurais des tableau de milliers d’élément, mais cela reste un principe important pour des tests de la couche service car je veux pouvoir tester mes données récupérées dans la base et vérifier que je récupère bien les bonnes.


Merci pour votre temps :p Encore une fois!


ZF2 et doctrine addict
profil stack overflow : http://stackoverflow.com/users/3333246/ … ab=profile

Hors ligne

 

#12 18-04-2014 14:11:58

Orkin
Administrateur
Lieu: Paris
Date d'inscription: 09-12-2011
Messages: 1261

Re: Tests unitaire avec doctrine, compréhension, appréhension

Ca te retourne une collection pas un tableau. Ca se comporte pareil mais tu peux faire plus de choses avec smile.

JGreco a écrit:

Ceci m'a permit de comprendre qu'en réalité l'entité Album est directement lié via l'entity Manager à la base de donnée et qu'il n'y à pas besoin de récupérer les données depuis la couche service, c'est bien cela ?

Oui et non, l'entity manager s'occupe de faire la requête pour toi via le repository de l'entité. Si elle en a pas c'est la classe EntityRepository qui doit être appelée qui implémente déjà le find, findAll etc ... qui fait la requête en fonction de ton SGBD (mysql, oracle, SQL Server etc ...) donc là dessus c'est OK par contre le fait de passer par une couche service ou non n'a rien à voir. Si tu ne passes pas par une couche service ça veut dire que tu fais l'appel dans un contrôleur (ou ailleurs mais en général dans le MVC c'est là, dans une aide de vue, un plugin etc ...) et ça n'a rien à faire ici. C'est simple l'entity manager ne doit être présent que dans des classes service. S'il est présent ailleurs tu ne respectes plus cette architecture.

Donc ta méthode de service fetchAll ne joue le rôle que de "proxy" vers la methode findAll du repository de l'entité que tu appels via l'entity manager.

Hors ligne

 

#13 18-04-2014 14:44:45

JGreco
Administrateur
Date d'inscription: 22-12-2012
Messages: 432

Re: Tests unitaire avec doctrine, compréhension, appréhension

Ouuhaaaaaa (/*pépites dans les yeux */)
J'en ai plein les yeux c'est trop beau ! Je viens de comprendre, l'utilité des collections !! c'est pas rien merci !
Bon j'ai enlevé ce proxy qui faisait un peu crade pour le remplacer par ce que tu as mis, en effet c'est cool !

A partir de ce que j'ai compris, j'aimerai savoir si j'ai fait les choses bien : voici mon test unitaire complet commenté.

Code:

    public function testCanFetchAllAlbum()
    {
        //On mock la classe Service afin d'avoir une instance de la méthode à tester
        $this->mockAlbumService = $this->getMock('Album\Service\AlbumService');
        //On va chercher tous nos album en utilisant l'EM et notre mapping d'Album
        $Album = $this->em->getRepository('Album\Entity\Album')->findAll();
        //On place le test en s'assurant que la méthode fetchAll est appellé qu'une fois et qu'elle retourne
        //bien une collection d'album
        $this->mockAlbumService->expects($this->once())->method('fetchAll')->will($this->returnValue($Album));

        //On fait notre assertion : est ce que notre méthode fetchAll renvoie une collection d'album réponse oui !
        $this->assertSame($this->mockAlbumService->fetchAll(), $Album);
    }

ZF2 et doctrine addict
profil stack overflow : http://stackoverflow.com/users/3333246/ … ab=profile

Hors ligne

 

#14 18-04-2014 14:50:53

Orkin
Administrateur
Lieu: Paris
Date d'inscription: 09-12-2011
Messages: 1261

Re: Tests unitaire avec doctrine, compréhension, appréhension

C'est normal t'as bindé le même objet ... Donc forcément c'est la même chose :p.

Logiquement t'es pas censé appeler ici non plus l'entity manager mais bon ... Pour tester si tu récupères bien une collection je testerais plus le type d'objet retourné plutôt que le contenu. Du coup le $Album il sert à rien. Faudrait que tu mock l'entity manager de ton service et tu appelles la méthode fetchAll sans mocker le service et tu tests le retour pour voir si tu as bien une collection par exemple.

Après je suis pas très doué en test donc à prendre avec des pincettes.

Hors ligne

 

#15 18-04-2014 15:03:30

JGreco
Administrateur
Date d'inscription: 22-12-2012
Messages: 432

Re: Tests unitaire avec doctrine, compréhension, appréhension

En fait j'avais décidé d'injecter dans les classes de test l'entity manager car pour tester mes services,  j'avais des erreurs de connexion sur la base de donnée...
Le fruit de mes recherche m'a orienté vers cette solution. Surement que dès que j'en saurais plus je constaterai que c'est inutile et je l'enlèverai, mais pour l'instant j'essaye juste de comprendre l'implémentation de tout cela, l'optimisation et le respect des règles d'architecture viendra après avoir compris.

Mocker l'entity manager de mon service c'est donc faire cela ?

Code:

$this->mockAlbumServiceEM = $this->getMock('Doctrine\ORM\EntityManager');

Je pense que non, car rien ne spécifie que c'est le ServiceAlbum, un petit indice s'il te plait ?


ZF2 et doctrine addict
profil stack overflow : http://stackoverflow.com/users/3333246/ … ab=profile

Hors ligne

 

#16 18-04-2014 15:06:11

Orkin
Administrateur
Lieu: Paris
Date d'inscription: 09-12-2011
Messages: 1261

Re: Tests unitaire avec doctrine, compréhension, appréhension

Réfléchis un peu smile.

Si tu mocke une classe Toto est-ce qu'elle va être de type Tata ? Non ! Bah là c'est pareil. L'entity manager de doctrine et ton service sont complètement différent le seul lien qu'il y a entre eux c'est que le service utilise l'entity manager (pas l'inverse) c'est tout.

Hors ligne

 

#17 18-04-2014 16:42:18

JGreco
Administrateur
Date d'inscription: 22-12-2012
Messages: 432

Re: Tests unitaire avec doctrine, compréhension, appréhension

Franchement ? J'ai cherché et j'ai pas tout saisi, j'ai vu ce lien là sur symfony http://symfony.com/fr/doc/current/cookb … abase.html

C'est le même principe dont tu me parles ?


ZF2 et doctrine addict
profil stack overflow : http://stackoverflow.com/users/3333246/ … ab=profile

Hors ligne

 

#18 19-04-2014 00:16:44

Orkin
Administrateur
Lieu: Paris
Date d'inscription: 09-12-2011
Messages: 1261

Re: Tests unitaire avec doctrine, compréhension, appréhension

Je te l'ai déjà expliqué l'histoire des couches pour les tests c'est le même principe ça change pas. Tu veux tout apprendre d'un coup et au final tu t'y perds complètement, là tu bloques sur des choses que tu as normalement compris puisque tu l'as déjà fait correctement. Au final comme le contexte change t'es complètement perdu donc concentres toi sur des choses simples.

Relis bien ça, le code et tes phrases. Remémores toi ce qu'est Doctrine\ORM\EntityManager, de quelle couche ça fait parti :

JGreco a écrit:

Mocker l'entity manager de mon service c'est donc faire cela ?

Code:

$this->mockAlbumServiceEM = $this->getMock('Doctrine\ORM\EntityManager');

Je pense que non, car rien ne spécifie que c'est le ServiceAlbum, un petit indice s'il te plait ?

Hors ligne

 

Pied de page des forums

Propulsé par PunBB
© Copyright 2002–2005 Rickard Andersson
Traduction par punbb.fr

Graphisme réalisé par l'agence Rodolphe Eveilleau
Développement par Kitpages