web-dev-qa-db-fra.com

Comment puis-je tester un contrôleur Symfony2?

Je souhaite utiliser autant que possible le développement piloté par les tests - c’est un excellent moyen de travailler.

Je suis troublé par le fait que les contrôleurs Symfony2 créent et renvoient un nouvel objet Response.

Je veux pouvoir effectuer des tests unitaires sur un contrôleur en isolation.

Comment faites-vous?

La solution est-elle de créer un contrôleur en tant qu'objet Plain Old PHP, de l'enregistrer en tant que service et d'utiliser Dependency Injection pour lui transmettre un nouvel objet Response (ou une usine Response)?

27
Lewis Bassett

Normalement, votre contrôleur connecte différents objets et les connecte dans le bon ordre. Peut-être qu'il appelle un référentiel, lit certains objets et les renvoie via la méthode de rendu. Peut-être qu'il appelle d'autres Handlers/Managers qui font des choses.

Cela signifie qu'un contrôleur est un composant de haut niveau. Le plus souvent, cela indique que les tests fonctionnels sont en ordre plutôt que les tests unitaires. Vous ne devez pas viser une couverture de code à 100% avec vos tests unitaires. Vous pouvez peut-être penser de cette façon: si vous testez tout ce que le contrôleur appelle (modèle, validation, formulaire, référentiel), qu'est-ce qui pourrait mal tourner? La plupart du temps, c'est quelque chose que vous n'observez que lorsque vous utilisez toutes les classes réelles impliquées dans la production.

Je tiens également à souligner que TDD ne signifie pas que tout doit être testé à l'unité. Il est correct de disposer de tests fonctionnels pour le code de haut niveau. Comme indiqué précédemment, si vous testez les composants de bas niveau avec des tests unitaires, vous ne devez tester que leur fonctionnement commun, ce que vous ne pouvez pas tester avec des simulacres car vous indiquez à ces simulacres la valeur de retour.

Si votre contrôleur ne se contente pas de brancher des parties du système, vous devez envisager de les restructurer en classes de bas niveau que vous pouvez tester avec des tests unitaires.

Donc, ma suggestion serait d'utiliser des tests fonctionnels pour tester vos contrôleurs et des tests unitaires pour tester vos modèles et votre logique métier.

Si vous rencontrez des difficultés avec les tests fonctionnels, vous pouvez lire ce qui suit:

53
Sgoettschkes

Utilisez des simulacres pour isoler les modèles et autres objets de la logique de la méthode du contrôleur principal, voir http://www.phpunit.de/manual/3.7/en/test-doubles.html#test-doubles.mock-objects

Je pense que dans les versions plus anciennes, vous pouvez vous moquer de la classe entière, mais avec la dernière version 3.6.10 de phpunit, il semble ne pas fonctionner Donc, je suppose que vous êtes laissé avec le modèle d'injection de dépendance

class objss{
    function ss(){
        $x = new zz();
        var_dump($x->z());
    }
}



class MoTest extends PHPUnit_Framework_TestCase{
    public function setUp(){

    }

    public function testA(){
        $class = $this->getMock('zzMock', array('z'), array(), 'zz');
        $class->expects($this->any())->method('z')->will($this->returnValue('2'));

        $obj = new objss();
        $this->assertEquals('2', $obj->ss());
    }
}
2
Artjom Kurapov

Tests unitaires

Refactorisez vos contrôleurs pour qu'ils soient des services: http://symfony.com/doc/current/cookbook/controller/service.html

Ensuite, vous pouvez facilement les tester à l’unité.

Test fonctionel

Bien sûr (comme cela a déjà été mentionné par d’autres), vous pouvez utiliser la variable WebTestCase comme décrit ici: http://symfony.com/doc/current/book/testing.html#functional-tests

1
Marcel Burkhard

Lewis - Je pensais que je pourrais sauter ici. L'approche ci-dessus vous permet de reproduire la meilleure partie de la logique de vos actions dans vos tests. Il n’ya rien de mal à cela, de nombreux frameworks (notamment RSPEC dans Rails) vous suggèrent d’effectuer des tests unitaires sur vos objets Controller ainsi que des tests fonctionnels. Cependant, étant donné votre exemple, je pense que je sauterais le test unitaire et choisirais une approche fonctionnelle. 

Le but d'un test dans mon esprit est de créer un environnement en mode bac à sable, de le tester et de rechercher les effets secondaires et les résultats directs. Si vous arrivez à un point où la plupart de vos tests isolent la méthode, il est probablement temps d'adopter une approche de test différente ou une approche différente pour l'écriture de votre classe. Étant donné qu’il s’agit d’un contrôleur et que, par nature, ils collent différents morceaux de la pile, je créerais votre bac à sable plus loin dans la pile. Plus précisément, j'utiliserais une approche comme celle-ci:

https://github.com/PolishSymfonyCommunity/SymfonyMockerContainer

A bien fonctionné pour moi :)

0
genexp