web-dev-qa-db-fra.com

Créer un simulacteur dans PHPUnit sans moquer de méthodes?

Lorsque je suis un appareil test mon code PHP avec PHPUnit, j'essaie de comprendre la bonne façon de se moquer d'un objet sans se moquer de ses méthodes.

Le problème est que si je n'appelle pas getMockBuilder()->setMethods(), toutes les méthodes de l'objet seront moquées et je ne peux pas appeler la méthode que je souhaite tester; Mais si j'étais do appel setMethods(), alors j'ai besoin de lui dire quelle méthode à moquer mais je ne veux pas se moquer de méthodes du tout. Mais je dois créer la moqueur afin que je puisse éviter d'appeler le constructeur dans mon test.

Voici un exemple trivial d'une méthode que je voudrais tester:

class Foobar
{
    public function __construct()
    {
        // stuff happens here ...
    }

    public function myMethod($s)
    {
        // I want to test this
        return (strlen($s) > 3);
    }
}

Je pourrais tester myMethod() avec:

$obj = new Foobar();
$this->assertTrue($obj->myMethod('abcd'));

Mais cela appellerait le constructeur de Foobar que je ne veux pas. Alors à la place j'essayerais:

$obj = $this->getMockBuilder('Foobar')->disableOriginalConstructor()->getMock();
$this->assertTrue($obj->myMethod('abcd'));

Mais appelant getMockBuilder() Sans utiliser setMethods() _ donnera à toutes ses méthodes à moquer et à renvoyer NULL, alors mon appel à myMethod() _ Retourne NULL sans toucher le code i l'intention de tester.

Ma solution de contournement a été ceci:

$obj = $this->getMockBuilder('Foobar')->setMethods(array('none'))
    ->disableOriginalConstructor()->getMock();
$this->assertTrue($obj->myMethod('abcd'));

Cela se moquera d'une méthode nommée "aucune", qui n'existe pas, mais PHPUnit s'en fiche. Il quittera MyMethod () non acquitté pour que je puisse l'appeler, et cela me laissera également désactiver le constructeur afin que je ne l'appelais pas. Parfait! Sauf que cela semble être de tricher avoir à spécifier un nom de méthode qui n'existe pas - "Aucun" ou "Blargh" ou "xyzzy".

Quelle serait la bonne façon de faire cela?

37
Brian Kendig

Vous pouvez passer null à setMethods() pour éviter de se moquer de méthodes. Passer un tableau vide va se moquer de toutes les méthodes. Ce dernier est la valeur par défaut pour les méthodes que vous avez trouvées.

Cela étant dit, je dirais que la nécessité de le faire pourrait signaler une faille dans la conception de cette classe. Cette méthode devrait-elle être faite statique ou déplacée vers une autre classe? Si la méthode ne nécessite pas d'instance complètement construite, c'est un signe pour moi qu'il pourrait s'agir d'une méthode utilitaire qui pourrait être rendue statique.

47
David Harkness

Un autre hacky, mais succinct Solution est simplement de répertorier le constructeur magique comme l'une des méthodes moquées:

$mock = $this->getMock('MyClass', array('__construct'));
3
Mike Petrovich

Ou vous pouvez simplement utiliser getMock() directement.

$mock = $this->getMock('MyClass', null, array(), null, false);

0
Ryan

Dans le cas de toute méthode, par exemple Cela s'appelle via l'entitémanager, peut être utilisé que vous pourrez peut-être utiliser ceci:

$this->entityManager
        ->expects($this->any())
        ->method($this->anything())
        ->willReturn($repository);
0
urlichsanais