Maison >développement back-end >tutoriel php >Analyse fonctionnelle des propriétés privées et méthodes de test PHPUnit

Analyse fonctionnelle des propriétés privées et méthodes de test PHPUnit

不言
不言original
2018-06-12 16:43:421435parcourir

Cet article présente principalement les fonctions de PHPUnit pour tester les propriétés et méthodes privées. Il analyse également en détail les techniques de fonctionnement pertinentes et les précautions d'utilisation de PHPUnit pour tester les propriétés et méthodes privées sous forme d'exemples auxquels les amis dans le besoin peuvent se référer. it

L'exemple de cet article décrit le test PHPUnit des propriétés privées et des fonctions de méthode. Partagez-le avec tout le monde pour votre référence, comme suit :

1. Méthodes privées dans la classe de test :

class Sample
{
  private $a = 0;
  private function run()
  {
    echo $a;
  }
}

Ce qui précède écrit simplement une classe contenant, une variable privée et une méthode privée. Pour les méthodes protégées et privées, puisqu'elles ne peuvent pas être appelées directement comme les méthodes publiques, il est très gênant d'utiliser phpunit pour des tests uniques, surtout lorsqu'une classe ne fournit qu'un petit nombre d'interfaces avec le monde extérieur et utilise un grand nombre de méthodes privées. situation interne.

Pour les méthodes protégées, il est recommandé d'utiliser l'héritage pour les tests, je n'entrerai donc pas dans les détails ici. Pour tester les méthodes privées, il est recommandé d'utiliser le mécanisme de réflexion de PHP. Sans plus attendre, voici le code :

class testSample()
{
    $method = new ReflectionMethod('Sample', 'run');
    $method->setAccessible(true); //将run方法从private变成类似于public的权限
    $method->invoke(new Sample()); //调用run方法
}

Si la méthode run est statique, par exemple :

private static function run()
{
  echo 'run is a private static function';
}

Ensuite, la fonction d'invocation peut également être écrite comme ceci :

$method->invoke(null); //只有静态方法可以不必传类的实例化

Si run doit également transmettre des paramètres, tels que :

private function run($x, $y)
{
  return $x + $y;
}

Ensuite, le code de test peut être modifié en :

$method->invokeArgs(new Sample(), array(1, 2));
//array中依次写入要传的参数。执行结果返回3

[Remarque] : Bien qu'il soit bon d'utiliser la réflexion pour tester les méthodes privées, la fonction setAccessible n'est prise en charge qu'après php5.3.2 (>=5.3.2)

2. Attributs privés get/set

Après avoir parlé des méthodes privées, regardons les propriétés privées. Prenons toujours la classe Sample comme exemple. pour obtenir ou définir la valeur de la propriété privée $a dans la classe Sample, vous pouvez utiliser la méthode suivante :

public function testPrivateProperty()
{
  $reflectedClass = new ReflectionClass('Sample');
  $reflectedProperty = $reflectedClass->getProperty('a');
  $reflectedProperty->setAccessible(true);
  $reflectedProperty->getValue(); //获取$a的值
  $reflectedProperty->setValue(123); //给$a赋值:$a = 123;
}

La méthode ci-dessus est toujours valable pour les attributs statiques.

À ce stade, il semble que tester des méthodes ou des propriétés privées soit devenu instantanément facile.

Pièce jointe : PHPunit testant les méthodes privées (original anglais)

Cet article fait partie d'une série sur les tests de code non testable :

  • Test des méthodes privées

  • Test du code qui utilise des singletons

  • Stubbing des méthodes statiques

  • Stubbing des dépendances codées en dur

Non, pas ces dépendances privées. Si vous avez besoin d'aide avec celles-ci, ce livre pourrait vous aider.

Une question que je reçois. maintes et maintes fois, quand on parle de tests unitaires, voici :

"Comment tester les attributs et méthodes privés de mes objets ?"

Supposons que nous ayons un class Foo :

<?php
class Foo
{
  private $bar = &#39;baz&#39;;
  public function doSomething()
  {
    return $this->bar = $this->doSomethingPrivate();
  }
  private function doSomethingPrivate()
  {
    return &#39;blah&#39;;
  }
}
?>

Avant d'explorer comment les attributs et méthodes protégés et privés peuvent être testés directement, voyons comment ils peuvent être testé indirectement.

Le test suivant appelle la méthode testDoSomething() qui à son tour appelle la méthode doSomethingPrivate() : le test ci-dessus suppose que testDoSomething() ne fonctionne correctement que lorsquetestDoSomethingPrivate() fonctionne correctement. Cela signifie que nous avons indirectement. testestDoSomethingPrivate(). Le problème avec cette approche est que lorsque le test échoue, nous ne savons pas directement où se trouve la cause première de l'échec. Cela peut être dans testDoSomething() ou testDoSomethingPrivate(). 🎜>

PHPUnit prend en charge la lecture des attributs protégés et privés via la méthode PHPUnit_Framework_Assert::readAttribute() ) qui existe pour exprimer des assertions sur les attributs protégés et privés :

<?php
class FooTest extends PHPUnit_Framework_TestCase
{
  /**
   * @covers Foo::doSomething
   * @covers Foo::doSomethingPrivate
   */
  public function testDoSomething()
  {
    $foo = new Foo;
    $this->assertEquals(&#39;blah&#39;, $foo->doSomething());
  }
}
?>

PHP 5.3.2 introduit la méthode ReflectionMethod::setAccessible() pour permettre l'invocation de méthodes protégées et privées via l'API Reflection :

<?php
class FooTest extends PHPUnit_Framework_TestCase
{
  public function testPrivateAttribute()
  {
    $this->assertAttributeEquals(
     &#39;baz&#39;, /* expected value */
     &#39;bar&#39;, /* attribute name */
     new Foo /* object     */
    );
  }
}
?>

Dans le test ci-dessus, nous testons directement testDoSomethingPrivate(). Lorsqu'il échoue, nous savons immédiatement où chercher la cause première.

Je suis d'accord avec Dave Thomas et Andy Hunt, qui écrivent dans leur livre "Pragmatic Unit Testing" :

<?php
class FooTest extends PHPUnit_Framework_TestCase
{
  /**
   * @covers Foo::doSomethingPrivate
   */
  public function testPrivateMethod()
  {
    $method = new ReflectionMethod(
     &#39;Foo&#39;, &#39;doSomethingPrivate&#39;
    );
    $method->setAccessible(TRUE);
    $this->assertEquals(
     &#39;blah&#39;, $method->invoke(new Foo)
    );
  }
}
?>
"En général, vous ne voulez pas rompre une encapsulation pour le plaisir de tester (ou comme disait maman, "n'exposez pas vos parties intimes !"). La plupart des temps, vous devriez pouvoir tester une classe en exerçant ses méthodes publiques. S'il existe une fonctionnalité importante cachée derrière un accès privé ou protégé, cela peut être un signe d'avertissement indiquant qu'il y a une autre classe qui a du mal à sortir. "

Donc : ce n'est pas parce que tester des attributs et des méthodes protégés et privés est possible que c'est une "bonne chose".

Ce qui précède est l'intégralité du contenu de cet article. J'espère qu'il sera utile à l'apprentissage de tout le monde. Pour plus de contenu connexe, veuillez faire attention au site Web PHP chinois !

Recommandations associées :

Analyse du mécanisme de verrouillage pessimiste implémenté par PHP et redis

Résumé de l'utilisation des fonctions variables en php

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn