另一个类中的PHPUnit模拟方法

时间:2019-03-07 11:29:56

标签: php mocking phpunit

我开始使用PHPUnit测试和模拟php中的方法。如果这些方法在同一类中,则没有问题。
但是我还不知道如何模拟另一个类中的方法。

class classA {
  public function funcA() {
    $classB = new classB();
    $value = $classB->getValue();
    return $value;
  }
}
class classB {
  public function getValue() {
    return "this is my value";
  }
}

如果getValue在classA中,则可以执行以下操作:

class testClassA {
  function testFuncA() {
    $mb = $this
      ->getMockBuilder(classA::class)
      ->setMethods(array('getValue'))
      ->getMock();
    $mb
      ->method('getValue')
      ->will($this->returnValue('my new value');
    $value = $mb->funcA();

    $this->assertEquals('my new value', $value);
  }
}

但是,在上面的情况下,我该怎么办呢?

修改:
Jon Stirling要求在构造函数中实例化classB而不是经过测试的方法
因此,让我们编辑classA

class classA {

  $private classB;

  public function __construct(){
    $this->classB = new classB();
  }

  public function funcA() {
    $value = $this->classB->getValue();
    return $value
  }
}

那怎么可能呢?

1 个答案:

答案 0 :(得分:0)

代替实际分离类,以便测试可以在测试时注入classB对象,答案是使用反射来替换类成员:

class classA {

    private $classB;

    public function __construct(){
        $this->classB = new classB();
    }

    public function funcA() {
        $value = $this->classB->getValue();
        return $value
    }
}


class testClassA {
    function testFuncA() {
        $mb = $this
            ->getMockBuilder(classB::class)
            ->setMethods(array('getValue'))
            ->getMock();

        $mb
            // XXX must be called EXACTLY once
            ->expects($this->once())
            ->method('getValue')
            ->will($this->returnValue('my new value');

        $ma = $this
            ->getMockBuilder(classA::class)
            ->setMethods([
                // XXX do not mock any methods except the constructor!
            ])
            // XXX avoid any side effects from classA's constructor:
            ->disableOriginalConstructor()
            ->getMock();

        // XXX inject the mock B into the mock A
        $reflector = new ReflectionClass($ma);
        $prop = $reflector->getProperty('classB');
        $prop->setAccessible(true);
        $prop->setValue($ma, $mb);

        $value = $ma->funcA();

        $this->assertEquals('my new value', $value);
    }
}

->expects()运算符视为断言。所有这些测试测试都是classA对其getValue成员调用$classB方法。 IMO不太有用。