12
votes

Comment tester les contrôleurs avec codeigniter?

J'ai une application Web PHP construite avec Codedigniter MVC Cadre. Je souhaite tester diverses classes de contrôleur. J'utilise toast pour tester unitaire. Mes contrôleurs n'ont aucun état, tout ce qu'ils traitent est enregistré en session ou transmis à la visualisation. Création d'un objet de session simulée et de tester si cela fonctionne correctement est simple (créez simplement un objet de simulation et injectez-le avec $ contrôleur-> session = $ maquette).

Ce que je ne sais pas, est de savoir comment travailler avec des vues. Dans CodeDigniter, les vues sont chargées comme suit: p> xxx pré>

puisque je ne veux pas modifier le code CI, je pouvais créer un chargeur simulé et remplacer l'original. Et ici réside dans le problème, je ne trouve pas un moyen de dériver une nouvelle classe de CI_Loader. p>

Si je n'inclut pas le fichier système / bibliothèques / loader.php, la classe CI_LOADER est indéfinie et je ne peux pas hériter de celui-ci: P>

class Loader_mock 
{
    public $real_loader;
    public $varijable = array();

    public function Loader_mock($real)
    {
        $this->real_loader = $real;
    }

    public function __call($name, $arguments) 
    {
        return $this->real_loader->$name($arguments);
    }

    public function __set($name, $value)
    {
        return $this->real_loader->$name = $value;
    }

    public function __isset($name)
    {
        return isset($this->real_loader->$name);
    }

    public function __unset($name)
    {
        unset($this->loader->$name);
    }

    public function __get($name)
    {
        return $this->real_loader->$name;
    }

    public function view($view, $vars = array(), $return = FALSE)
    {
        $varijable = $vars;
    }
}


0 commentaires

5 Réponses :


2
votes

Ma solution actuelle consiste à modifier le code de codeigniter à utiliser requis_once au lieu d'avoir besoin. Voici le correctif que je vais envoyer aux développeurs CI au cas où une personne doit faire de même jusqu'à ce qu'ils acceptent:

diff --git a/system/codeigniter/Common.php b/system/codeigniter/Common.php
--- a/system/codeigniter/Common.php
+++ b/system/codeigniter/Common.php
@@ -100,20 +100,20 @@ function &load_class($class, $instantiate = TRUE)
        // folder we'll load the native class from the system/libraries folder.
        if (file_exists(APPPATH.'libraries/'.config_item('subclass_prefix').$class.EXT))
        {
-               require(BASEPATH.'libraries/'.$class.EXT);
-               require(APPPATH.'libraries/'.config_item('subclass_prefix').$class.EXT);
+               require_once(BASEPATH.'libraries/'.$class.EXT);
+               require_once(APPPATH.'libraries/'.config_item('subclass_prefix').$class.EXT);
                $is_subclass = TRUE;
        }
        else
        {
                if (file_exists(APPPATH.'libraries/'.$class.EXT))
                {
-                       require(APPPATH.'libraries/'.$class.EXT);
+                       require_once(APPPATH.'libraries/'.$class.EXT);
                        $is_subclass = FALSE;
                }
                else
                {
-                       require(BASEPATH.'libraries/'.$class.EXT);
+                       require_once(BASEPATH.'libraries/'.$class.EXT);
                        $is_subclass = FALSE;
                }
        }


0 commentaires

1
votes

Je ne peux pas vous aider beaucoup avec les tests, mais je peux vous aider à étendre la bibliothèque CI.

Vous pouvez créer votre propre my_loader classe intérieure / application / bibliothèques / My_loader.php . xxx

codeigniter le verra automatiquement. Il suffit de mettre les fonctions que vous souhaitez remplacer dans la bibliothèque d'origine. Tout le reste utilisera l'original.

Pour plus d'informations, consultez le Manuel CI Page de création de classes de système de base .


1 commentaires

+1 pour l'idée. Toutefois, une règle d'or des tests d'unité est que vous ne devriez pas avoir besoin de modifier le système pour activer les crochets pour les tests d'unités. Idéalement, les classes qui ne font pas partie de la suite de tests unitaires ne doivent avoir aucun bagage de test unitaire avec eux. En outre, garder tout le code de test de l'unité pour une seule classe de tests dans le même fichier facilite la gestion (et également supprimer le code de test de l'unité lors du déploiement de la production).



1
votes

Je suis impressionné par le code que vous essayez d'utiliser.

Alors maintenant, je me demande comment la classe "Hooks" de Codeigniter pourrait être utile à votre problème?

http://codeigniter.com/user_guide/general/hooks.html

genre Cordialement, Rein Groot


1 commentaires

+1 pour la pointe. Il semble que cela puisse être faisable, mais de manière quelque peu gênante. J'ai décidé de corriger le Codeigniter à la place - c'est un simple changement, et j'espère que cela entrera dans le code CI traditionnel un jour (comme je ne vois aucune raison pour laquelle cela ne devrait pas), donc je n'aurai pas à la corriger quand Les nouvelles versions sont libérées.



4
votes

Alternativement, vous pouvez le faire:

$CI =& get_instance();
$CI = load_class('Loader');

class MockLoader extends CI_Loader
{
    function __construct()
    {
        parent::__construct();
    }
}


0 commentaires

0
votes

Le contrôleur ne doit pas contenir de logique de domaine. Les tests d'unité n'ont aucun sens ici.

Au lieu de cela, je testerais les contrôleurs et les vues avec des tests d'acceptation.


4 commentaires

Eh bien ... Bien qu'il n'y ait pas de logique de domaine dans les contrôleurs, ils sont responsables de la gestion de la saisie de l'utilisateur. Et modifier l'état de couche de modèle basé sur cette entrée. C'est là que l'on se concentrerait sur les tests de l'unité pour les contrôleurs.


Je ne pense pas que le contrôleur puisse modifier l'état de rien dans la couche de modèle. Il devrait simplement recevoir la demande puis transmettre à la couche modèle (après la gestion de la sécurité Web, etc.). Si vous modifiez des entités ou des données, je suppose que vous devriez tester. Mais vous ne devriez pas faire cela en premier lieu.


Si vous passez le nom d'utilisateur et le mot de passe sur le calque modèle, vous en modifiez l'état. Ou si vous envoyez un titre d'article à enregistrer, vous modifiez également l'état de couche modèle. Et ce que vous avez appelé "Sécurité Web" est quelque chose qui doit être effectué dans la couche modèle (à l'exception de la prévention de la CSRF ... cela pourrait être mieux fait lors de l'initialisation de la demande d'instance ). Cependant, il est possible que nous utilisions le même terme pour un concepts .


Je pense que je vous ai mal compris. Je pensais en altérer que vous vouliez modifier directement une entité du contrôleur. Merci pour le lien.