我有一个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
?
答案 0 :(得分:5)
您可以在这里找到几个不同的方向:
答案 1 :(得分:3)
关键是在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()
方法“接缝”,因为它们是可以在不更改周围代码的情况下插入假货的点。