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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/6711647/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-26 01:02:59  来源:igfitidea点击:

In PHPUnit, how do I mock parent methods?

phptestingmockingphpunit

提问by james

I want to test a class method that calls upon a parent method with the same name. Is there a way to do this?

我想测试一个调用同名父方法的类方法。有没有办法做到这一点?

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

采纳答案by Gordon

You dont mock or stub methods in the Subject-under-Test (SUT). If you feel you have the need to mock or stub a method in the parent of the SUT, it likely means you shouldnt have used inheritance, but aggregation.

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

You mock dependenciesof the Subject-under-Test. That means any other objects the SUT requires to do work.

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

回答by user1029767

An approach that works to my is the implementation of a wrap to the parent call on the child class, and finally mock those wrap.

一种对我有用的方法是对子类上的父调用执行换行,最后模拟这些换行。

You code modified:

您修改了代码:

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

回答by Dallas Caley

Here is how I did it, I have no idea if this is correct but it works:

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

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

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

now in the test i do:

现在在测试中我做:

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

what the ?

什么?

My reasoning here is that all i really want to test is whether or not my variable got set. i don't really care about what happens in the parent method but since you can't prevent the parent method from being called what i do is mock the dependent methods of the parent method.

我的理由是,我真正想要测试的是我的变量是否已设置。我并不真正关心父方法中发生的事情,但是由于您无法阻止调用父方法,因此我所做的是模拟父方法的依赖方法。

now go ahead and tell me i'm wrong :)

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

回答by Manish Trivedi

I'm totally agree with @Gordon. I have same issue but I have tried few tricky concept.

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

My scenario is like

我的场景就像

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

I have created another parent class with same name "Parent" and treat as a stub and include my stub class(parent) and ignore to actual parent (Actual parent class set into auto-load and stub-parent must be be included )

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

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

Now I create mock object of Child class (via Mock-builder) and complete my test cases with end of assertSame. :-)

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

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

回答by physicalattraction

A satisfying solution in my opinion is to create a class that inherits from your class under test and override the implementation of the method you want to give another implementation. This has its flaws: it does not always work, e.g. for already overridden methods and for private methods.

在我看来,一个令人满意的解决方案是创建一个从被测类继承的类,并覆盖要提供另一个实现的方法的实现。这有其缺陷:它并不总是有效,例如对于已经覆盖的方法和私有方法。

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