Как создать экземпляр юнит-теста? - PullRequest
4 голосов
/ 14 декабря 2009

У меня есть класс Carpenter, который выполняет свою работу, используя объект Lathe и Wood.

class Carpenter
{
    function Work()
    {
        $tool = new Lathe();
        $material = new Wood();
        $tool->Apply($material);
    }
}

Lathe зависит от интерфейса, называемого Material, поэтому я могу легко выполнить юнит-тест Lathe, выдав ему фальшивый Material в моем юнит-тесте. Wood не зависит ни от чего, поэтому его также легко проверить.

interface Material {
    // Various methods...
}

interface Tool {
    function Apply(Material $m);
}

class Wood implements Material  {
    // Implementations of Material methods
}

class Lathe {
    function Apply(Material $m) {
        // Do processing
    }
}

Однако Carpenter зависит от конкретных классов Lathe и Wood, поскольку он должен создавать их экземпляры. Это означает, что в текущем состоянии я не могу выполнить модульное тестирование метода Work() без непреднамеренного тестирования Lathe и Wood.

Как мне поменять свой дизайн на юнит-тест Carpenter?

Ответы [ 2 ]

5 голосов
/ 14 декабря 2009

Здесь вы можете выбрать несколько направлений:

  • Используйте Конструкторский впрыск и просто введите инструмент и материалы в плотник.
  • Если внедрение экземпляров по какой-то причине не работает (возможно, из-за того, что вам нужно создавать новые экземпляры для каждого вызова метода Work), вы можете вместо этого ввести Абстрактные фабрики .
  • Вы также можете использовать подход Factory Method , описанный ctford, но он требует от вас также создания переопределений, специфичных для теста, чтобы иметь возможность проводить модульное тестирование, и, хотя это вполне допустимо, это просто больше работы, и во многих случаях другие альтернативы лучше и гибче.
3 голосов
/ 14 декабря 2009

Ключ должен отделить создание объекта от использования объекта в Carpenter.

class Carpenter
{
    function getTool() {
        return new Lathe();
    }
    function getMaterial() {
        return new Wood();
    }
    function Work()
    {
        $tool = getTool();
        $material = getMaterial();
        $tool->Apply($material);
    }
}

Таким образом, вы можете переопределить методы getTool() и getMaterial() в классе TestCarpenter и добавить свои собственные Material и Tool подделки.

Методы getTool() и getMaterial() также могут быть проверены отдельно.

Michael Feathers будет называть методы getTool() и getMaterial() "швами", потому что они являются точками, в которые могут быть вставлены подделки без изменения окружающего кода.

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