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".
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());
});
});
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%
Est-ce que quelqu'un connaitrait le moyen de tester l'appel à une méthode de classe?
merci d'avance.
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 :-)
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.