В PHPUnit, как я могу издеваться над родительскими методами?


Я хочу протестировать метод класса, который вызывает родительский метод с тем же именем. Есть ли способ сделать это?

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?
    }
}
Author: james, 2011-07-15

5 answers

Вы не издеваетесь и не заглушаете методы в тестируемом объекте (SUT). Если вы чувствуете, что вам нужно высмеять или заглушить метод в родительском элементе SUT, это, скорее всего, означает, что вам не следовало использовать наследование, а агрегацию.

Вы издеваетесь над зависимостями тестируемого объекта. Это означает, что любые другие объекты, необходимые SUT для выполнения работы.

 16
Author: Gordon, 2011-07-15 19:02:33

Подход, который работает для меня, - это реализация переноса на родительский вызов дочернего класса и, наконец, имитация этого переноса.

Вы изменили код:

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
Author: user1029767, 2012-10-24 14:32:20

Вот как я это сделал, я понятия не имею, правильно ли это, но это работает:

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

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

Теперь в тесте я делаю:

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

Что за?

Мое рассуждение здесь заключается в том, что все, что я действительно хочу проверить, это то, установлена ли моя переменная. мне на самом деле все равно, что происходит в родительском методе, но, поскольку вы не можете запретить родительскому методу вызываться, я высмеиваю зависимые методы родительского метода.

А теперь продолжайте и скажите мне, что я ошибаюсь:)

 4
Author: Dallas Caley, 2012-03-21 20:21:05

Я полностью согласен с @Гордоном. У меня та же проблема, но я попробовал несколько хитрых концепций.

Мой сценарий похож на

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

Я создал другой родительский класс с тем же именем "Родитель" и рассматриваю его как заглушку и включаю свой класс-заглушку (родитель) и игнорирую фактического родителя (фактический родительский класс, установленный в режим автоматической загрузки, и должен быть включен заглушка-родитель)

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

Теперь я создаю макет объекта дочернего класса (с помощью макета-конструктора) и завершаю свои тестовые примеры с окончанием assertSame. :-)

$this->assertSame($mock, $mock->save());
 2
Author: Manish Trivedi, 2013-09-14 09:43:23

Удовлетворительным решением, на мой взгляд, является создание класса, наследуемого от вашего тестируемого класса, и переопределение реализации метода, который вы хотите предоставить другой реализации. У этого есть свои недостатки: это не всегда работает, например, для уже переопределенных методов и для частных методов.

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
Author: physicalattraction, 2015-09-21 13:20:15