PHPUnit макет метода в другом классе - PullRequest
0 голосов
/ 07 марта 2019

Я начал использовать 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 был в классе A, я мог бы сделать следующее:

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

Но как мне это сделать в том случае, как у нас выше?

Edit:
Джон Стирлинг попросил создать экземпляр класса B в конструкторе вместо проверенного метода
Итак, давайте отредактируем класс A

class classA {

  $private classB;

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

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

Так как же это возможно?

1 Ответ

0 голосов
/ 11 марта 2019

Вместо того, чтобы фактически отделить ваши классы так, чтобы тест мог внедрить объект 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. Не слишком полезен, ИМО.

...