[kahlan] tester l'appel à une méthode

Par fzed51, il y a 9 ans


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, il y a 9 ans

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.

fzed51, il y a 9 ans

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 :-)