Почему мой PHPUnit макет клиента Predis не соответствует моим ожиданиям?

#php #mocking #redis #phpunit #predis

#php #издевательство #redis #phpunit #predis

Вопрос:

Я пытаюсь смоделировать клиент Predis в тесте PHPUnit. Когда я вызываю метод, который я пытался смоделировать, в конце теста PHPUnit сообщает мне, что ожидание не было выполнено.

Вот пример кода, который воспроизводит мою проблему:

 class MockRedisTest extends PHPUnit_Framework_TestCase {
private $mockRedis;

public function testMockRedis() {

    $mockRedis =  $this->getMock('Predis\Client');

    $mockRedis->expects(  $this->once())
      ->method("exists")
      ->with($this->equalTo("query-key"))
      ->will($this->returnValue(true));

    $mockRedis->exists("query-key");
}
  

}

И PHPUnit считает, что метод не был вызван:

1) Ошибка ожидания MockRedisTest::testMockRedis для имени метода равна при вызове 1 раз (ов). Ожидалось, что метод будет вызван 1 раз, фактически вызвано 0 раз.

Почему? Это потому, что клиент Predis, похоже, использует __call для ответа на вызовы методов, которые соответствуют командам redis?

ОБНОВЛЕНИЕ: у меня создается впечатление, что это как-то связано с методом __call. Изменение кода на это работает:

 public function testMockRedis() {

    $mockRedis =  $this->getMock('Predis\Client');

    $mockRedis->expects(  $this->once())
      ->method("__call")
      ->with("exists", $this->equalTo(array("query-key")))
      ->will($this->returnValue(true));

    $mockRedis->exists("query-key");
}
  

Не уверен, что я доволен этим, хотя. Есть ли лучший способ имитировать классы, которые используют __вызов прокси-методов?

Ответ №1:

Я думаю, вы можете использовать

 $mockRedis =  $this->getMock('Predis\Client', array('exists'));
// ...
  

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

Ответ №2:

Если вы хотите создать макет определенного профиля сервера и убедиться, что вы не вызываете методы другой версии сервера, используйте

 <?php
$mockRedis = $this->getMock('Predis\Client', array_keys((new PredisProfilesServerVersion26)->getSupportedCommands()));
  

Ответ №3:

Для Phpunit 5 используйте

 $this->createPartialMock('Predis\Client', ['exists']);
  

Чтобы ваш макет знал о методе «exists» (или любой другой собственной команде redis)