Модульное тестирование с помощью макетов (PHP) - PullRequest
4 голосов
/ 23 января 2012

У меня есть класс вроде:

class Foo {
    function getCurrentBar() {
        $model = Query::findByPk($this->getSession()->get('current_bar')); // Pseudocode...

        return $model;
    }
}

Таким образом, в моем приложении в основном по одному столбцу за раз, и он сохраняется в сеансе как целое число.Я часто вызываю вспомогательную функцию, которая находит экземпляр модели, она делает запрос БД.Кэширование тоже есть, но это не имеет значения.

Мой вопрос такой: как мне выполнить модульное тестирование с этим?Есть классы, которые я проверяю, которые нуждаются в этом.Я думаю, что я мог бы изменить сеанс, чтобы он содержал идентификатор, но тогда это означает, что мне нужно иметь соответствующую модель в базе данных.

Будет ли лучший способ добавить метод setCurrentBar() только для целей модульного тестирования?Тогда я мог бы смоделировать объект bar и установить его, и он будет использоваться для всех модульных тестов.Имеет ли это смысл?

Ответы [ 3 ]

6 голосов
/ 23 января 2012

Ответ на самом деле - это внедрение зависимостей, но зависимость, которую вы хотите контролировать, это источник столбцов, а не сам столбец.

class Foo {
  private $query;

  function __construct($query)
  {
    $this->query = $query;
  }

  function getCurrentBar() {
    $model = $this->query->findByPk($this->getSession()->get('current_bar')); // Pseudocode...

    return $model;
  }
}

Итак, в вашем рабочем коде есть

$query = new Query() // assuming findByPk() is made a normal non-static method
$realFoo = new Foo($query);

но для модульного тестирования ...

$testFoo = new Foo(new MockQuery());

, где MockQuery - это фиктивная версия вашего Query класса, которая возвращает макет баров .

0 голосов
/ 28 января 2013

Вы также можете протестировать частичный фиктивный объект в качестве временного, пока система DI не будет установлена.

class Foo {
    function getCurrentBar() {
        $model = $this->getQueryResult($this->getSession()->get('current_bar')); // Pseudocode...
        return $model;
    }
    function getQueryResult($queryParams)
    {
        return Query::findByPk($queryParams);
    }
}

Затем проведите тест, похожий на этот ...

$myObjectToTest = $this->getMock('Foo', array('getQueryResult'), array(), '', true, true, true);
$myObjectToTest->expects($this->once())
               ->method('getQueryResult')
               ->with($whateverTheQueryParametersAre)
               ->will($this->returnValue($someResult));
$myObjectToTest->getCurrentBar();
0 голосов
/ 23 января 2012

Вы можете попробовать использовать внедрение зависимостей .

Передача экземпляра Bar в конструктор Foo

class Foo
{
    private _bar;

    function __construct (Bar $bar)
    {
        $this->_bar = $bar;
    }

    public function getCurrentBar()
    {
        return $this->_bar;
    }
}

Затем вы можете внедрить свой ложный объект Bar при запускеваш тест.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...