En général, on ne teste pas ou on ne simule pas directement les méthodes privées et protégées.
Ce que vous voulez tester, c'est le public API de votre classe. Tout le reste est un détail d'implémentation pour votre classe et ne devrait pas "casser" vos tests si vous le changez.
Cela vous aide également lorsque vous constatez que vous "ne pouvez pas obtenir une couverture de code à 100 %", car votre classe contient peut-être du code que vous ne pouvez pas exécuter en appelant l'API publique.
Vous ne voulez généralement pas faire ça
Mais si votre classe ressemble à ça :
class a {
public function b() {
return 5 + $this->c();
}
private function c() {
return mt_rand(1,3);
}
}
je peux comprendre la nécessité de vouloir faire un simulacre de c() puisque la fonction "random" est un état global et que vous ne pouvez pas le tester.
La solution "propre?/verbeuse?/surcompliquée-peut-être?/j'aime-autant-que-comme-c'est-habituel
class a {
public function __construct(RandomGenerator $foo) {
$this->foo = $foo;
}
public function b() {
return 5 + $this->c();
}
private function c() {
return $this->foo->rand(1,3);
}
}
maintenant il n'y a plus besoin de simuler "c()" puisqu'il ne contient pas de globales et que vous pouvez tester gentiment.
Si vous ne voulez pas ou ne pouvez pas supprimer l'état global de votre fonction privée (mauvaise chose, mauvaise réalité ou votre définition de mauvais peut être différente), vous pouvez puede test contre la maquette.
// maybe set the function protected for this to work
$testMe = $this->getMock("a", array("c"));
$testMe->expects($this->once())->method("c")->will($this->returnValue(123123));
et exécutez vos tests contre ce simulacre puisque la seule fonction que vous retirez ou simulez est "c()".
Pour citer le livre "Pragmatic Unit Testing" :
"En général, vous ne voulez pas rompre l'encapsulation pour le plaisir de tester (ou comme maman le disait, "n'exposez pas vos parties intimes !"). La plupart du temps, vous devriez être en mesure de tester une classe en exerçant ses méthodes publiques. Si une fonctionnalité importante est cachée derrière un accès privé ou protégé, cela peut être un signe d'alerte qu'il y a une autre classe à l'intérieur qui se bat pour sortir."
Un peu plus : Why you don't want test private methods.