Как создать unit test создание экземпляра?
У меня есть класс Carpenter, который работает с использованием объектов Lathe и Wood.
class Carpenter
{
function Work()
{
$tool = new Lathe();
$material = new Wood();
$tool->Apply($material);
}
}
Lathe зависит от интерфейса с именем Material, поэтому я могу легко unit test Lathe дать ему подделку Material в моем unit test. 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, потому что он должен создавать экземпляры из них. Это означает, что, поскольку он в настоящее время стоит, я не могу unit test метод Work() без непреднамеренного тестирования Lathe и Wood.
Как мне изменить свой дизайн на unit test Carpenter?
Ответы
Ответ 1
Здесь есть несколько разных направлений:
- Используйте Инъекции конструктора и просто вставляйте инструмент и экземпляры материалов в плотника.
- Если инъекции экземпляров не работают по какой-либо причине (возможно, потому, что вам нужно создавать новые экземпляры для каждого вызова метода Work), вы можете добавить Абстрактные фабрики.
- Вы также можете использовать метод Factory Метод, описанный ctford, но для этого требуется, чтобы вы также создавали переопределения для тестирования, чтобы иметь возможность unit test, и хотя это полностью действительная вещь сделать это, это просто больше работы, и во многих случаях другие альтернативы лучше и гибче.
Ответ 2
Ключ состоит в том, чтобы отделить создание объекта от использования объекта в 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() "швами", потому что они являются точками, где подделки можно вставлять без изменение окружающего кода.