Question

Comment tester les méthodes concrètes d'une classe abstraite avec PHPUnit?

Je suppose que je devrais créer un objet dans le cadre du test. Bien que je n’aie pas la moindre idée de la meilleure pratique à suivre ou de savoir si PHPUnit le permet.

Était-ce utile?

La solution

Le test unitaire des classes abstraites ne signifie pas nécessairement le test de l'interface, car les classes abstraites peuvent avoir des méthodes concrètes, et ces méthodes concrètes peuvent être testées.

Lors de l’écriture de code de bibliothèque, il n’est pas si rare d’avoir certaines classes de base que vous souhaitez étendre dans votre couche d’application. Et si vous voulez vous assurer que le code de la bibliothèque est testé, vous avez besoin de moyens pour utiliser les méthodes concrètes des classes abstraites.

Personnellement, j'utilise PHPUnit, et il a ce qu'on appelle des stubs et des objets fictifs pour vous aider à tester ce genre de choses.

Directement du Manuel de PHPUnit :

abstract class AbstractClass
{
    public function concreteMethod()
    {
        return $this->abstractMethod();
    }

    public abstract function abstractMethod();
}

class AbstractClassTest extends PHPUnit_Framework_TestCase
{
    public function testConcreteMethod()
    {
        $stub = $this->getMockForAbstractClass('AbstractClass');
        $stub->expects($this->any())
             ->method('abstractMethod')
             ->will($this->returnValue(TRUE));

        $this->assertTrue($stub->concreteMethod());
    }
}

Un objet factice vous donne plusieurs choses:

  • vous n'êtes pas obligé d'avoir une implémentation concrète de la classe abstraite et pouvez vous en tirer avec un stub à la place
  • vous pouvez appeler des méthodes concrètes et affirmer qu'elles fonctionnent correctement
  • si la méthode concrète se base sur la méthode non implémentée (abstraite), vous pouvez remplacer la valeur renvoyée par la méthode will () PHPUnit

Autres conseils

C'est une bonne question. Je cherchais ça aussi.
Heureusement, PHPUnit a déjà getMockForAbstractClass () , par exemple,

protected function setUp()
{
    $stub = $this->getMockForAbstractClass('Some_Abstract_Class');
    $this->_object = $stub;
}

Important:

Notez que cela nécessite PHPUnit > 3.5.4. un bogue dans les versions précédentes.

Pour mettre à niveau vers la dernière version:

sudo pear channel-update pear.phpunit.de
sudo pear upgrade phpunit/PHPUnit

Il est à noter qu'à compter de PHP 7, les classes anonymes a été ajouté. Cela vous donne un moyen supplémentaire de configurer un test pour une classe abstraite, qui ne dépend pas des fonctionnalités spécifiques à PHPUnit.

class AbstractClassTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @var AbstractClass
     */
    private $testedClass;

    public function setUp()
    {
        $this->testedClass = new class extends AbstractClass {

            protected function abstractMethod()
            {
                // Put a barebones implementation here
            }
        };
    }

    // Put your tests here
}

Eran, votre méthode devrait fonctionner, mais elle va à l’encontre de la tendance à écrire le test avant le code réel.

Ce que je suggérerais est d'écrire vos tests sur la fonctionnalité souhaitée d'une sous-classe non abstraite de la classe abstraite en question, puis d'écrire à la fois la classe abstraite et la sous-classe d'implémentation, puis de lancer le test.

Vos tests doivent évidemment tester les méthodes définies de la classe abstraite, mais toujours via la sous-classe.

La réponse de Nelson est fausse.

Les classes abstraites ne nécessitent pas que toutes leurs méthodes soient abstraites.

Les méthodes implémentées sont celles que nous devons tester.

Ce que vous pouvez faire est de créer une fausse classe de bout sur le fichier de test unitaire, de l'étendre à la classe abstraite et de n'implémenter que ce qui est requis, sans aucune fonctionnalité, bien sûr, et de le tester.

A bientôt.

Si vous ne souhaitez pas sous-classer la classe abstraite uniquement pour effectuer un test unitaire sur les méthodes déjà implémentées dans la classe abstraite, vous pouvez essayer de voir si votre infrastructure vous permet de > fictif de classes abstraites.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top