338 votes

Meilleures pratiques pour tester les méthodes protégées avec PHPUnit

J'ai trouvé la discussion sur avez-vous test privé de la méthode informative.

J'ai décidé, que, dans certaines classes, je veux avoir protégé méthodes, mais de les tester. Certaines de ces méthodes sont statiques et court. Parce que la plupart des méthodes publiques de les utiliser, je vais probablement être en mesure de retirer en toute sécurité les tests plus tard. Mais pour commencer avec une approche TDD et éviter de débogage, j'ai vraiment envie de les tester.

J'ai pensé à la suivante:

  • Méthode de l'Objet en tant que conseillé dans une réponse semble être exagéré pour cela.
  • Commencer avec méthodes publiques et lors de la couverture de code est donné par la hausse des tests de niveau, tourner à se protéger et à supprimer les tests.
  • Hériter d'une classe avec un testable interface protégées méthodes publiques

Quelle est la meilleure pratique? Est-il autre chose?

Il semble que JUnit change automatiquement protégé méthodes pour être publique, mais je n'ai pas eu un regard plus profond sur elle. PHP ne permet pas cela au travers de la réflexion.

490voto

uckelman Points 7228

Si vous utilisez PHP5 (> = 5.3.2) avec PHPUnit, vous pouvez tester vos méthodes privées et protégées à l’aide de réflexion pour définir les publics avant d’exécuter vos tests :

61voto

robert.egginton Points 119

teastburn a la bonne approche. Encore plus simple est d’appeler directement la méthode et renvoyer la réponse :

On peut l’appeler tout simplement dans vos tests de :

58voto

troelskn Points 51966

Vous semblez être au courant déjà, mais je vais reformuler de toute façon, C'est un mauvais signe, si vous avez besoin de tester les méthodes protected. Le but d'un test unitaire, est de tester l'interface d'une classe, et protégés sont les méthodes de mise en œuvre de détails. Cela dit, il y a des cas où cela a du sens. Si vous utiliser l'héritage, vous pouvez voir une super-classe en fournissant une interface pour la sous-classe. Donc, ici, vous devez tester la méthode protégée (Mais jamais à un privé ). La solution pour cela est de créer une sous-classe pour objectif de test, et de l'utiliser pour exposer les méthodes. Ex.:

class Foo {
  protected function stuff() {
    // secret stuff, you want to test
  }
}

class SubFoo extends Foo {
  public function exposedStuff() {
    return $this->stuff();
  }
}

Notez que vous pouvez toujours remplacer l'héritage de la composition. Lors des tests de code, il est généralement beaucoup plus facile de traiter avec un code qui utilise ce modèle, de sorte que vous pouvez considérer cette option.

25voto

teastburn Points 175

J'aimerais proposer une légère variation de getMethod() définie dans uckelman de réponse.

Ce changement de version de getMethod() par la suppression des valeurs codées en dur et en simplifiant l'utilisation un peu. Je recommande d'ajouter à votre PHPUnitUtil classe comme dans l'exemple ci-dessous, ou à votre PHPUnit_Framework_TestCase-l'extension de la classe (ou, je suppose, à l'échelle mondiale pour votre PHPUnitUtil fichier).

Depuis Maclasse est instanciée de toute façon et ReflectionClass peut prendre une chaîne ou un objet...

class PHPUnitUtil {
    /**
     * Get a private or protected method for testing/documentation purposes.
     * How to use for MyClass->foo():
     *      $cls = new MyClass();
     *      $foo = PHPUnitUtil::getPrivateMethod($cls, 'foo');
     *      $foo->invoke($cls, $...);
     * @param object $obj The instantiated instance of your class
     * @param string $method The name of your private/protected method
     * @return ReflectionMethod The method you asked for
     */
    public static function getPrivateMethod($obj, $name) {
      $class = new ReflectionClass($obj);
      $method = $class->getMethod($name);
      $method->setAccessible(true);
      return $method;
    }
    // ... some other functions
}

J'ai également créé un alias de la fonction getProtectedMethod() pour être plus explicite ce qui est prévu, mais que l'une est à vous.

Cheers!

13voto

Michael Johnson Points 1474

Je pense que troelskn est proche. Je pourrais faire cela à la place :

Ensuite, mettre en place quelque chose comme ceci :

Ensuite, vous exécutez vos tests sur TestClassToTest.

Il devrait être possible de générer automatiquement des classes d’extension en analysant le code. Je ne serais pas surpris si PHPUnit offre déjà un tel mécanisme (bien que je n’ai pas vérifié).

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X