Tester Les Classes Abstraites

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

Je m'attendrais à ce que je doive créer une sorte d'objet dans le cadre du test. Cependant, je n'ai aucune idée de la meilleure pratique pour cela ou si PHPUnit le permet.

122
demandé sur David Harkness 2008-10-10 10:03:07

6 réponses

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

Il n'est pas si rare, lors de l'écriture de code de bibliothèque, d'avoir une certaine classe de base que vous prévoyez d'é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 UT les méthodes concrètes des classes abstraites.

Personnellement, J'utilise PHPUnit, et il a donc appelé stubs et objets simulés pour vous aider à tester ce genre de choses.

Directement à partir de PHPUnit manuel:

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());
    }
}

Objet Mock vous donne plusieurs choses:

  • Vous n'êtes pas obligé d'avoir une implémentation concrète de la classe abstraite, et vous pouvez vous en sortir avec stub à la place
  • Vous pouvez appeler des méthodes concrètes et affirmer qu'elles fonctionnent correctement
  • si la méthode concrète repose sur une méthode non implémentée (abstraite), vous pouvez tronquer la valeur de retour avec will () méthode PHPUnit
211
répondu Victor Farazdagi 2014-10-13 11:40:36

C'est une bonne question. J'ai été la recherche de ce trop.
Heureusement, PHPUnit a déjàgetMockForAbstractClass() méthode pour ce cas, par exemple

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

Important:

Notez que cela nécessite PHPUnit > 3.5.4. Il y avait un bug dans les versions précédentes.

Pour passer à la nouvelle version:

sudo pear channel-update pear.phpunit.de
sudo pear upgrade phpunit/PHPUnit
36
répondu takeshin 2018-04-17 10:06:01

Il convient de noter qu'à partir de PHP 7, le support des classes anonymes a été ajouté. Cela vous donne une avenue supplémentaire pour configurer un test pour une classe abstraite, qui ne dépend pas de la fonctionnalité spécifique à 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
}
9
répondu GordonM 2018-02-20 15:47:01

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ère est d'écrire vos tests sur la fonctionnalité désiré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, et enfin d'exécuter le test.

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

1
répondu 2008-11-12 18:48:10

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 stub 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 tester cela.

Acclamations.

1
répondu skqr 2009-09-23 15:19:58

Si vous ne voulez pas sous-classer la classe abstraite juste pour effectuer un test unitaire sur les méthodes qui sont déjà implémentées dans la classe abstraite, vous pouvez essayer de voir si votre framework vous permet de mock abstract classes.

0
répondu hangy 2008-11-12 19:06:25