Эквивалент простейшего “частичного издевательства” в PHPUnit?

StackOverflow https://stackoverflow.com/questions/1164192

  •  18-09-2019
  •  | 
  •  

Вопрос

Я пытаюсь перенести кучу тестов с SimpleTest на PHPUnit, и мне было интересно, есть ли эквивалент для SimpleTest частичные насмешки.

Обновить:Кажется, я не могу найти в документах ничего, что указывало бы на то, что эта функция доступна, но мне пришло в голову, что я мог бы просто использовать подкласс.Это хорошая или плохая идея?

class StuffDoer {
    protected function doesLongRunningThing() {
        sleep(10);
        return "stuff";
    }
    public function doStuff() {
        return $this->doesLongRunningThing();
    }
}
class StuffDoerTest {
    protected function doesLongRunningThing() {
        return "test stuff";
    }
}
class StuffDoerTestCase extends PHPUnit_Framework_TestCase {
    public function testStuffDoer() {
        $sd = new StuffDoerTest();
        $result = $sd->doStuff();
        $this->assertEquals($result, "test stuff");
    }
}
Это было полезно?

Решение

При чтении связанной страницы самый простой частичный макет кажется макетом, в котором переопределены только некоторые методы.Если это правильно, то эта функциональность обрабатывается обычным макетом PHPUnit.

Внутри a PHPUnit_Framework_TestCase, вы создаете макет с

$mock = $this->getMock('Class_To_Mock');

Который создает макет экземпляра, где все методы ничего не делают и возвращают null .Если вы хотите переопределить только некоторые методы, второй параметр для getMock представляет собой массив методов для переопределения.

$mock = $this->getMock('Class_To_Mock', array('insert', 'update'));

создаст макет экземпляра Class_To_Mock с помощью insert и update функции удалены, готовы к указанию возвращаемых ими значений.

Эта информация находится в документы phpunit.

Примечание, этот ответ показывает более актуальные примеры кода для версий PHPUnit, начиная с 5.4

Другие советы

PHPUnit_Framework_TestCase::getMock устарел начиная с phpunit 5.4.Мы можем использовать setMethods вместо этого.

setMethods(array $methods) может быть вызван для объекта Mock Builder, чтобы указать методы, которые должны быть заменены настраиваемым тестовым двойником.Поведение других методов не изменяется.Если вы вызовете setMethods(null), то никакие методы не будут заменены.

https://phpunit.de/manual/current/en/test-doubles.html

$observer = $this->getMockBuilder(Observer::class)
                 ->setMethods(['update'])
                 ->getMock();

Обратите внимание, что вышеизложенное getMock является PHPUnit_Framework_MockObject_MockBuilder::getMock.(phpunit5.6)

Я не думаю, что PHPUnit поддерживает частичные макеты для тестируемой системы.Если вы пытаетесь изолировать методы, то я уверен, что ваша реализация работает - я тоже это делал.

Однако я стараюсь избегать этого по нескольким причинам.

Во-первых, он очень тесно связывает ваш тест с внутренней реализацией класса.Вас действительно волнует, вызван ли метод doesLongRunningThing был вызван, или более важно, чтобы "долгосрочное дело" было сделано?

Во-вторых, когда я сталкиваюсь с этим, это всегда заставляет меня задуматься, выполняет ли у меня один класс работу за двоих.Ан извлечь класс рефакторинг мог бы быть в порядке вещей.Тестирование становится намного проще, если doesLongRunningThing() становится его собственным классом, даже с помощью одного метода.

Я считаю, что решение состоит в том, чтобы внедрить сервисы, от которых зависит ваш SUT (http://en.wikipedia.org/wiki/Dependency_injection).Это также делает DoesLongRunningThing реализация более поддается проверке.

Не вдаваясь в интерфейсы, вот что я бы сделал:

class DoesLongRunningThing {
    public function execute() {
        sleep(10);
        return "stuff";
    }
}

class StuffDoer {
    protected $doesLongRunningThing;

    public function setLongRunningThinger(DoesLongRunningThing $obj) {
        $this->doesLongRunningThing = $obj;
    }

    public function doStuff() {
        return $this->doesLongRunningThing->execute();
    }
}

Теперь над этим легко издеваться:

class StuffDoerTestCase extends PHPUnit_Framework_TestCase {
    public function testStuffDoer() {
        $dlrtMock = $this->getMock('DoesLongRunningThing');
        $dlrtMock->expects($this->any())->will($this->returnValue("test stuff"));

        $sd = new StuffDoer();
        $sd->setLongRunningThinger($dlrtMock);
        $result = $sd->doStuff();
        $this->assertEquals($result, "test stuff");
    }
}
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top