Bonjour,

Bonjour, après avoir vu le tuto sur kahlan, j'ai voulu mettre en pratique les tests sur mon routeur.
Sur le principe, il est très simple : j'initialise une route, si elle match avec l'URI, elle exéctue l'action qui lui est affectée.
Soit une closure, soit une chaine qui correspond à une methode@controleur.
Actuellement, je n'arrive pas à tester le fait que si je passe une action "methode@controleur", j'exécute la méthode "methode" d'une instance du "controleur".

Ce que je fais

Ma classe Route

<?php
class Route {

    private $path;
    private $action;
    private $name;

    function __construct($name, $path, $action) {
        $this->name = $name;
        $this->action = $action;
        $this->path = $path;
    }

    function executeAction() {
        $matches = [];
        $action = $this->action;
        if (is_callable($action)) {
            return call_user_func($action);
        }
        if (is_string($action) && preg_match('/^(\w+)@([\w\\\\]+)$/', $action, $matches)) {
            $nom_methode = $matches[1];
            $nom_controleur = $matches[2];
            if (class_exists($nom_controleur)) {
                $methodes = get_class_methods($nom_controleur);
                if (array_search($nom_methode, $methodes) !== false) {
                    $controleur = new $nom_controleur();
                    return call_user_func([$controleur, $nom_methode]);
                }
            }
        }
        throw new Exception("Impossible d'executer l'action de la route {$this->name}");
    }

}

Mes spec

<?php
describe('Execution', function() {

    it('should execut an route with action/controler action', function() {

    class foo{ public function bar(){} }

    $new_route = new Route('name_path', 'uri', 'bar@foo');
    allow('foo')->toReceive('bar');
    expect($new_route->executeAction());
    });
});

Ce que j'obtiens

Pour l'instant si j'execute ce test j'ai un beau 100%. Le problème c'est que si je change l'action en bad@foo j'obtiens toujours un 100%

Ce que je veux

Est-ce que quelqu'un connaitrait le moyen de tester l'appel à une méthode de classe?

merci d'avance.

2 réponses


fzed51
Auteur
Réponse acceptée

Ca y est !!!!

J'ai enfin trouvé. Et comme d'habitude les solutions les plus simples ne sont pas forcement les plus évidentes.

<?php
    it('should execut an route with action/controler action', function() {

        class foo{ public function bar(){} public function bad(){} }

        $new_route = new Route('name_path', 'uri', 'bar@foo');
        expect('call_user_func')->toBeCalled()->with(Arg::toMatch(function($arg){
        return (is_array($arg))
                && (count($arg) == 2)
                && (is_a($arg[0], 'foo'))
                && ($arg[1] == 'bar'); 
            }));
        $new_route->executeAction();
    });

J'utilise un Matcher personalisé ...

Edit : Si personne ne m'a aidé sur ce post, j'espère que cette solution pourra aider quelqu'un... un jour... et éviter 2 jour de casse tête :-)

fzed51
Auteur

J'ai un début de réponse.

Pour l'instant, je m'arrête à ça :

    <?php
    it('should execut an route with action/controler action', function() {

        class foo{ public function bar(){} public function bad(){} }

        $new_route = new Route('name_path', 'uri', 'bar@foo');
        expect('call_user_func')->toBeCalled()->with(Arg::toBeA('array'));
        expect('call_user_func')->toBeCalled()->with(Arg::toContain('bar'));
        $new_route->executeAction();
    });

Mais ça ne me satisfait pas : je teste que j'appelle une méthode d'un "callable", que cette méthode s'appelle "bar", mais je ne sais pas si elle est appelée sur le bon objet.

Je reste ouvert à toutes propositions.