Question En PHPUnit, comment simuler les méthodes parentes?


Je veux tester une méthode de classe qui appelle une méthode parente avec le même nom. Y a-t-il un moyen de faire cela?

class Parent {

    function foo() {
        echo 'bar';
    }
}

class Child {

    function foo() {
            $foo = parent::foo();
            return $foo;
    }
}

class ChildTest extend PHPUnit_TestCase {

    function testFoo() {
        $mock = $this->getMock('Child', array('foo'));

        //how do i mock parent methods and simulate responses?
    }
}

18
2017-07-15 18:33


origine


Réponses:


Vous ne vous moquez pas ou ne stubez pas les méthodes dans l'objet-sous-test (SUT). Si vous estimez que vous avez besoin de simuler ou de modifier une méthode dans le parent du SUT, cela signifie probablement que vous ne devriez pas avoir utilisé l'héritage, mais l'agrégation.

Vous vous moquez dépendances du sujet sous test. Cela signifie que tout autre objet requis par le SUT est de travailler.


16
2017-07-15 19:02



Une approche qui fonctionne avec my est l'implémentation d'un wrap à l'appel parent sur la classe enfant, et finalement se moquer de ces wrap.

Votre code a été modifié:

class Parent {

    function foo() {
        echo 'bar';
    }
}

class Child {

    function foo() {
            $foo = $this->parentFooCall();
            return $foo;
    }
    function parentFooCall() {
            return parent::foo();
    }
}

class ChildTest extend PHPUnit_TestCase {

    function testFoo() {
        $mock = $this->getMock('Child', array('foo', 'parentFooCall'));

        //how do i mock parent methods and simulate responses?
    }
 }

8
2017-10-24 14:10



Voici comment je l'ai fait, je n'ai aucune idée si c'est correct mais ça marche:

class parentClass {
    public function whatever() {
        $this->doSomething();
    }
}

class childClass extends parentClass {
    public $variable;
    public function subjectUnderTest() {
        $this->variable = 'whocares';
        parent::whatever();
    }
}

maintenant dans le test je fais:

public function testSubjectUnderTest() {
    $ChildClass = $this->getMock('childClass', array('doSomething'))
    $ChildClass->expects($this->once())
               ->method('doSomething');
    $ChildClass->subjectUnderTest();
    $this->assertEquals('whocares', $ChildClass->variable);
}

quoi le

Mon raisonnement ici est que tout ce que je veux vraiment tester, c'est si oui ou non ma variable a été définie. Je ne me soucie pas vraiment de ce qui se passe dans la méthode parente mais comme vous ne pouvez pas empêcher la méthode parente d'être appelée, je simule les méthodes dépendantes de la méthode parente.

maintenant vas-y et dis-moi que je me trompe :)


4
2018-03-21 20:21



Je suis totalement d'accord avec @Gordon. J'ai le même problème mais j'ai essayé quelques concepts délicats.

Mon scénario est comme

class Parent { // Actual-Parent Class
    function save() {
        // do something
        return $this
    }
}

class Child extends Parent {
   // Subject under test
    function save() {
          // do something
          return parent::save();
    }
}

J'ai créé une autre classe parente avec le même nom "Parent" et je la traite comme un stub et j'inclus ma classe de stub (parent) et je l'ignore vers le parent réel (la classe parent réelle définie dans auto-load et stub-parent doit être incluse)

class Parent { //Stub-Parent class
    function save() {
        return $this
    }
}

Maintenant, je crée un objet simulé de la classe Child (via Mock-Builder) et termine mes cas de test avec la fin de assertSame. :-)

$this->assertSame($mock, $mock->save());

2
2017-09-14 09:43



À mon avis, une solution satisfaisante consiste à créer une classe qui hérite de votre classe testée et à remplacer l’implémentation de la méthode que vous souhaitez implémenter. Cela a ses défauts: cela ne fonctionne pas toujours, par ex. pour les méthodes déjà surchargées et pour les méthodes privées.

class Parent
{
    function bar()
    {
        echo 'bar';
    }
}

class Child extends Parent
{
    function foo()
    {
        parent::bar();
        echo 'foo';
    }
}

class mockChild extends Child
{
    function bar()
    {
        echo 'baz';
    }
}

class ChildTest extends PHPUnit_TestCase 
{
    function testFoo() {
        $sut = new mockChild();
        $sut->foo();
    }
} 

0
2017-09-21 13:20