Test delle classi astratte


Risposte:


240

Il test unitario di classi astratte non significa necessariamente testare l'interfaccia, poiché le classi astratte possono avere metodi concreti e questi metodi concreti possono essere testati.

Non è così raro, quando si scrive un codice libreria, avere una certa classe base che si prevede di estendere nel livello dell'applicazione. E se vuoi assicurarti che il codice della libreria sia testato, hai bisogno di mezzi per UT i metodi concreti delle classi astratte.

Personalmente, utilizzo PHPUnit e ha i cosiddetti stub e oggetti finti per aiutarti a testare questo tipo di cose.

Direttamente dal manuale di 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());
    }
}

L'oggetto finto ti dà diverse cose:

  • non è necessario disporre di un'implementazione concreta della classe astratta e invece è possibile cavarsela con lo stub
  • puoi chiamare metodi concreti e affermare che funzionano correttamente
  • se il metodo concreto si basa su un metodo non implementato (astratto), è possibile stub il valore restituito con il metodo will () PHPUnit

38

Questa è una buona domanda. Ho cercato anche questo.
Fortunatamente, PHPUnit ha già un getMockForAbstractClass()metodo per questo caso, ad es

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

Importante:

Nota che ciò richiede PHPUnit> 3.5.4. Si è verificato un errore nelle versioni precedenti.

Per eseguire l'aggiornamento alla versione più recente:

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

Sembra interessante ma saresti testato contro il finto? Come sarebbero i test? IE: estendere la simulazione nel test case e testare con la classe di test estesa?
stefgosselin,

34

Va notato che a partire dal PHP 7 è stato aggiunto il supporto per le classi anonime . Questo ti dà una strada aggiuntiva per impostare un test per una classe astratta, che non dipende dalla funzionalità specifica di 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
}

4
Grazie per questo! L'uso di una classe anonima in PHPUnit mi ha dato molta flessibilità nella creazione dei miei vari test.
Alice Wonder,

1

Ehi, il tuo metodo dovrebbe funzionare, ma va contro la tendenza a scrivere il test prima del codice reale.

Quello che suggerirei è di scrivere i tuoi test sulla funzionalità desiderata di una sottoclasse non astratta della classe astratta in questione, quindi scrivere sia la classe astratta che la sottoclasse di implementazione, ed infine eseguire il test.

I tuoi test dovrebbero ovviamente testare i metodi definiti della classe astratta, ma sempre tramite la sottoclasse.


Trovo una risposta arbitraria: hai una classe astratta 'A' con un metodo 'foo ()' comune. Questo metodo 'foo ()' viene utilizzato nel complesso tutte le classi 'B' e 'C', entrambe derivano da 'A'. Quale classe sceglieresti di testare 'foo ()'?
user3790897,

1

La risposta di Nelson è sbagliata.

Le classi astratte non richiedono che tutti i loro metodi siano astratti.

I metodi implementati sono quelli che dobbiamo testare.

Quello che puoi fare è creare una classe stub falsa sul file di test unitario, estenderla alla classe astratta e implementare solo ciò che è richiesto senza alcuna funzionalità, ovviamente, e testarlo.

Saluti.


0

Se non si desidera sottoclassare la classe astratta solo per eseguire un test unitario sui metodi che sono già implementati nella classe astratta, si potrebbe provare a vedere se il proprio framework consente di deridere classi astratte.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.