Как создать экземпляр модульного теста?

У меня есть 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 ответа

Решение

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

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

Ключ должен отделить создание объекта от использования объекта в 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() Методы также могут быть проверены отдельно.

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

Другие вопросы по тегам