在PHPUnit中,如何模拟父方法?

时间:2011-07-15 18:33:18

标签: php testing mocking 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?
    }
}

5 个答案:

答案 0 :(得分:20)

你不要在被测对象(SUT)中模拟或存根方法。如果您觉得需要在SUT的父级中模拟或存根方法,则可能意味着您不应该使用继承,而是聚合。

您模拟了测试对象的依赖项。这意味着SUT需要工作的任何其他对象。

答案 1 :(得分:8)

对我有用的方法是在子类上实现父调用的包装,最后模拟那些包装。

您修改了代码:

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?
    }
 }

答案 2 :(得分:4)

我是这样做的,我不知道这是否正确但是有效:

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

是什么?

我的理由是,我真正想测试的是我的变量是否设置好了。我真的不关心父方法中发生了什么,但由于你无法阻止调用父方法,我所做的就是模拟父方法的依赖方法。

现在继续告诉我我错了:)

答案 3 :(得分:2)

我完全赞同@Gordon。我有同样的问题,但我尝试了一些棘手的概念。

我的情景就像

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

我创建了另一个具有相同名称“Parent”的父类,并将其视为存根并包含我的存根类(父级)并忽略实际父级(实际父级设置为自动加载,并且必须包含存根父级) )

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

现在我创建Child类的模拟对象(通过Mock-builder)并使用assertSame结束完成我的测试用例。 : - )

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

答案 4 :(得分:0)

在我看来,一个令人满意的解决方案是创建一个继承自测试类的类,并覆盖您想要给另一个实现的方法的实现。这有它的缺点:它并不总是有效,例如已经被覆盖的方法和私有方法。

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