Zend FR

Consultez la FAQ sur le ZF avant de poster une question

Vous n'êtes pas identifié.

#1 03-11-2014 10:05:52

JGreco
Modérateur
Date d'inscription: 22-12-2012
Messages: 421

Doctrine, tests unitaires, entityManager

Bonjour à tous,

J'ai un soucis depuis quelques temps déjà, c'est à propos des tests et de doctrine, j'aimerai savoir comment mocker l'entityManager doctrine. Le but est tout simple je ne veux absolument pas qu'il insert quoique ce soit en base de donnée lors des tests, mais qu'il puisse quand même opérer des selects.

J'ai encore beaucoup de mal a faire des tests unitaires quels qu'ils soient sur Zf2.

Mon problème est le suivant :

J'ai un objet que je considère en gros comme une boite à outils(Toolbox) que j'injecte dans mes services. Cet objet récupère mes deux entityManager (l'un pour une base de donnée en PDO, l'autre une bdd doctrine) ainsi que d'autre dépendance (classe utils qui possède des méthodes d'envoi de mails, d'écriture de log, etc...).

Voici le code d'une méthode que j'aimerai tester :

Code:

[lang=php]
 public function saveProforma($datas)
    {
        $connection = $this->emdoctrine->getConnection();
        $connection->beginTransaction();
        try {
            $connection->insert('ProformaGroup', $datas['datas']['ProformaGroup']);
            $lastProformaID = $connection->lastInsertId();
            foreach ($datas['datas']['orders'] as $fetchID => $order) {
                $order['ProformaOrders']['idProforma'] = $lastProformaID;
                $orders = explode(',', $order['ProformaOrders']['regroupData']);
                foreach ($orders as $dataOrder) {
                    $selected = new ProformaAlreadySelected();
                    $selected->setTypeOrder($datas['datas']['ProformaGroup']['typeOrder']);
                    $selected->setDataOrder($dataOrder);
                    $selected->setIdProforma($lastProformaID);
                    $selected->setDateLastModified(new \DateTime('now', $this->timeZone));
                    $this->emdoctrine->persist($selected);
                    $this->emdoctrine->flush($selected);
                }
                $connection->insert('ProformaOrders', $order['ProformaOrders']);
                $lastInsertId = $connection->lastInsertId();
                foreach ($order['ProformaAddress'] as $type => $address) {
                    $address['idOrder'] = $lastInsertId;
                    $connection->insert('ProformaAddress', $address);
                }
                foreach ($order['ProformaItem'] as $items) {
                    foreach ($items as $item) {
                        $item['idOrder'] = $lastInsertId;
                        $item['codCdeCli'] = $order['codCdeCli'];
                        $connection->insert('ProformaItem', $item);
                    }
                }
            }
            $connection->commit();
        } catch (\Exception $e) {
            $connection->rollback();
            $this->utils->log(
                "Le proforma n'a pas pu être enregistré : " . $e->getMessage(),
                false,
                true
            );
            return false;
        }
        return $lastProformaID;
    }

En gros cette méthode traite toutes les données que je récupère de ma première base pour les insérer dans la deuxième base via doctrine(et avec quelques traitements), je dois tester cela. Je dois donc mocker les méthodes, persist et flush pour le repository ProformaAlreadySelected, la méthode insert et commit pour l'entityManager.

Le seul soucis, c'est que quoi que je teste de ce que j'ai trouvé sur le net pour mock les entity manager doctrine, cela ne marche pas dans mon cas...

Voici mon constructeur de la méthode collé plus haut :

Code:

[lang=php]

    public function __construct(ToolboxService $toolbox, ConfiguredDatas $configuredDatas)
    {
        $this->toolboxService = $toolbox;
        $this->emDoctrine = $this->toolboxService->getEmDoctrine();
        $this->utils = $this->toolboxService->getUtils();
        $this->configuredDatas = $configuredDatas;
        $this->timeZone = new \DateTimeZone('Europe/Paris');
    }

J'ai eu plusieurs pistes sur le net et testé beaucoup d'autre dans mon coin mais je ne sais absolument pas ou aller, sachant que je n'ai eu que des échecs.. durant tous mes tests.

Merci d'avance pour votre coup de main smile

Dernière modification par JGreco (05-11-2014 10:11:53)


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

Hors ligne

 

#2 03-11-2014 12:09:24

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

Re: Doctrine, tests unitaires, entityManager

Salut, tu devrais trouver de quoi avancer ici wink : https://github.com/zf-fr/zfr-oauth2-ser … er/Service

Hors ligne

 

#3 03-11-2014 13:53:58

JGreco
Modérateur
Date d'inscription: 22-12-2012
Messages: 421

Re: Doctrine, tests unitaires, entityManager

Bonjour Orkin,
j'avais déjà testé sa solution de faire un getMock() de l'ObjectManager afin de créer la dépendance de mon objet Toolbox sauf que j'ai cette erreur dès le premier FindAll ou méthode de ce type :

Code:

 Fatal error:  Call to a member function findAll() on a non-object in C:\wamp\www\project\module\Invoice\src\Invoice\Service\IndexService.php on line 50

Du coup j'arrive pas a mocker l'ObjectManager et j'arrive pas a identifier pourquoi.

Le findAll en question ici est cette ligne :

Code:

[lang=php]
$this->emDoctrine->getRepository('Invoice\Entity\Config')->findAll();

Du coup vu que j'ai mock emDoctrine avec

Code:

[lang=php]
$this->getMock('Doctrine\Common\Persistence\ObjectManager')

Pourquoi l'erreur sur findAll ?

Dernière modification par JGreco (03-11-2014 13:59:01)


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

Hors ligne

 

#4 03-11-2014 14:14:21

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

Re: Doctrine, tests unitaires, entityManager

Et bien je t'encourage à bien lire comment il fait ses tests tu vas comprendre d'où vient ton erreur. De plus sans voir ton code et juste des petits bouts ça va jamais avancer.

Hors ligne

 

#5 03-11-2014 17:46:12

JGreco
Modérateur
Date d'inscription: 22-12-2012
Messages: 421

Re: Doctrine, tests unitaires, entityManager

Toujours pas... j'ai beau voir comment il fait j'arrive pas à l'adapter à mon architecture.

Une question il fait dans son code une interface sur laquelle pointe ses ZfrOAuth2Test\Server\Asset\SelectableObjectRepository

A quoi sert cette interface et surtout l'extends selectable ? J'ai un doute mais si c'est confirmé c'est peut être ma solution.


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

Hors ligne

 

#6 03-11-2014 22:47:50

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

Re: Doctrine, tests unitaires, entityManager

Bah c'est justement un mock de cette interface, tous les repository doctrine étendent ObjectRepository.

Ensuite regarde un peu ce qui est fait là :

Code:

[lang=php]
$this->clientRepository->expects($this->once())
                               ->method('find')
                               ->with('client_id')
                               ->will($this->returnValue($client));

$this->objectManager->expects($this->once())
                            ->method('persist')
                            ->with($this->isInstanceOf('ZfrOAuth2\Server\Entity\Client'));

Et toi :

Code:

[lang=php]
$this->emDoctrine->getRepository('Invoice\Entity\Config')->findAll();

Gardes en mémoire que se sont des mocks tu ne peux pas récupérer un répository depuis un mock et encore moins un findAll(). C'est à toi de simuler ce qui doit être fait en fonction des méthodes que tu appelles.

Hors ligne

 

#7 04-11-2014 13:15:12

JGreco
Modérateur
Date d'inscription: 22-12-2012
Messages: 421

Re: Doctrine, tests unitaires, entityManager

Merci Orkin c'était la reformulation que je cherchais j'ai bien mieux compris comment marchent les TU et doctrine avec cette explication et je peux enfin avancer sur les TU, merci beaucoup.


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

Hors ligne

 

#8 05-11-2014 10:15:55

JGreco
Modérateur
Date d'inscription: 22-12-2012
Messages: 421

Re: Doctrine, tests unitaires, entityManager

Bonjour,

Je bloque a nouveau sur une partie de ma configuration des tests unitaires. Actuellement pour récupérer mon service manager voici ce que je fais :

Code:

[lang=php]
    /**
     * Builds a new service manager
     */
    public static function getServiceManager()
    {
        $serviceManager = new ServiceManager(new ServiceManagerConfig(
            isset(static::$config['service_manager']) ? static::$config['service_manager'] : array()
        ));
        $serviceManager->setService('ApplicationConfig', static::$config);
        $serviceManager->setFactory('ServiceListener', 'Zend\Mvc\Service\ServiceListenerFactory');

        /** @var $moduleManager \Zend\ModuleManager\ModuleManager */
        $moduleManager = $serviceManager->get('ModuleManager');
        $moduleManager->loadModules();
        //$serviceManager->setAllowOverride(true);
        return $serviceManager;
    }

Du coup ici je ne récupère que ce qui concerne mes services, absolument rien sur les factory de controller, et encore moins mes invokables de form_elements, comment pourrais-je inclure dans le service manager ces éléments ?
Dois-je dupliquer cette méthode pour les autres éléments (j'avais testé mais sans grand succès) ?

Y a peut être une manière de faire qui m'échappe pour l'instant, si vous avez une idée ce serait sympa.

Merci.


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

Hors ligne

 

#9 05-11-2014 13:59:11

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

Re: Doctrine, tests unitaires, entityManager

Je suis pas très doué en tests donc regarde comment c'est fait sur le repo que je t'ai donné. Et de mémoire tu n'as pas à injecter le service manager. Le but c'est pas de tester que le service manager fonctionne bien (ça c'est déjà fait dans les tests du ZF) mais de tester ta logique métier donc un mock devrait suffire.

Hors ligne

 

#10 06-11-2014 09:48:32

JGreco
Modérateur
Date d'inscription: 22-12-2012
Messages: 421

Re: Doctrine, tests unitaires, entityManager

Orkin a écrit:

Je suis pas très doué en tests donc regarde comment c'est fait sur le repo que je t'ai donné. Et de mémoire tu n'as pas à injecter le service manager. Le but c'est pas de tester que le service manager fonctionne bien (ça c'est déjà fait dans les tests du ZF) mais de tester ta logique métier donc un mock devrait suffire.

Pour le service manager c'est très utile de l'injecter bien sur, en réalité, Ocramius est à l'origine de ce code, et je suis allé voir dans Zend\Test\Util\ModuleLoader (il me semblait pas y a voir ce dossier quand j'ai commencé sur zf2) et qu'y vois-je ? Presque le même code que j'ai mis plus haut.
j'en déduit donc qu'il y a du y a voir une Pull request de Ocramius sur cette partie là.

Sur tous mes devs j'ai une bonne couverture de code, jusqu’à maintenant, mais il persiste pas mal de chose que je n'arrive pas a tester d'ou mes questions en fait, mais j'ai refait des tests et j'y arrive maintenant.

Quand on parle de formulaire en fait, c'est plus facile de tester cela dans un ControllerTest.
Après c'est sur, je trouve personnellement que le module de test de zf2 est beaucoup plus difficile d'approche qu'il n'y parait, et trouver des infos, bonne pratiques, etc... deviens vite un parcours du combattant dès qu'on parle de Test unitaires... C'est dommage mais bon on s'y fait.

Merci pour ton aide en tous cas Orkin, à bientôt.

Dernière modification par JGreco (06-11-2014 09:49:13)


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

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