Question

Pour les objets qui composent un autre objet dans le cadre de leur mise en œuvre, ce qui est la meilleure façon d'écrire le test unitaire de sorte que l'objet principal est testé? Trivial exemple:

class myObj { 
    public function doSomethingWhichIsLogged()
    {
        // ...
        $logger = new logger('/tmp/log.txt');
        $logger->info('some message');
        // ...
    }
}

Je sais que l'objet pourrait être conçu de telle sorte que la dépendance de l'objet enregistreur pourrait être injecté et donc moqué dans un test unitaire, mais ce n'est pas toujours le cas - dans des scénarios plus complexes, vous avez besoin de composer d'autres objets ou faire des appels des procédés statiques.

Comme nous ne voulons pas tester l'objet enregistreur, seul le myObj, comment allons-nous procéder? Est-ce que nous créons une écrasa « double » avec le script de test? Quelque chose comme:

class logger
{
    public function __construct($filepath) {}
    public function info($message) {}
}

class TestMyObj extends PHPUnit_Framework_TestCase 
{
    // ...
}

Cela semble réalisable pour les petits objets, mais serait une douleur pour les API plus complexes où le SUT dépendu sur les valeurs de retour. En outre, si vous voulez tester les appels à l'objet de dépendance de la même a été possible avec des objets fantaisie? Est-il un moyen d'objets se moquant qui sont instanciés par le SUT plutôt que d'être adoptée en?

J'ai lu la page de manuel sur simulacres mais il ne semble pas couvrir cette situation où la dépendance se compose plutôt que agrégées. Comment faites-vous?

Était-ce utile?

La solution

Comme vous semblez être au courant déjà, béton classe facilite le test dur dépendances (ou carrément impossible). Vous devez découpler cette dépendance. Un simple changement, qui ne casse pas l'API existante, est par défaut le comportement actuel, mais fournir un crochet pour la remplacer. Il y a plusieurs façons que cela pourrait être mis en œuvre.

Certaines langues ont des outils qui peuvent injecter des classes dans le code simulacres, mais je ne sais pas de quoi que ce soit comme ça pour PHP. Dans la plupart des cas, vous seriez probablement mieux refactorisation votre code de toute façon.

Autres conseils

Après troelskn conseiller voici un exemple de base de ce que vous devez faire.

<?php

class MyObj
{
    /**
     * @var LoggerInterface
     */
    protected $_logger;

    public function doSomethingWhichIsLogged()
    {
        // ...
        $this->getLogger()->info('some message');
        // ...
    }

    public function setLogger(LoggerInterface $logger)
    {
        $this->_logger = $logger;
    }

    public function getLogger()
    {
        return $this->_logger;
    }
}


class MyObjText extends PHPUnit_Framework_TestCase
{
    /**
     * @var MyObj
     */
    protected $_myObj;

    public function setUp()
    {
        $this->_myObj = new MyObj;
    }

    public function testDoSomethingWhichIsLogged()
    {
        $mockedMethods = array('info');
        $mock = $this->getMock('LoggerInterface', $mockedMethods);
        $mock->expects($this->any())
             ->method('info')
             ->will($this->returnValue(null));

        $this->_myObj->setLogger($mock);

        // do your testing
    }
}

Plus d'informations sur les objets fantaisie se trouve dans le manuel .

On dirait que j'ai mal compris la question, je vais essayer à nouveau:

Vous devez utiliser le modèle singleton ou une usine de l'enregistreur, si elle est pas déjà trop tard:

class LoggerStub extends Logger {
    public function info() {}
}
Logger::setInstance(new LoggerStub());
...
$logger = Logger::getInstance();

Si vous ne pouvez pas modifier le code, vous pouvez utiliser un fourre-tout classe qui sature __ call ()

class GenericStub {
    public function __call($functionName, $arguments) {}
}

Il est en fait une extension assez nouvelle pour la surcharge de classe PHP publié par les mêmes gars qui construisent PHPUnit. Il vous permet de passer outre le nouvel opérateur dans le cas où vous ne pouvez pas factoriser le code, malheureusement il est pas si simple à installer sur Windows.

L'URL est http://github.com/johannes/php -test-assistants / blob / maître /

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