何时嘲笑,何时不嘲笑。
如果我要在以下示例中为MyObject-> doSomething()编写单元测试:
class Factory implements FactoryInterface
{
public function create($name) {
return new MyOtherObject($name);
}
}
class MyOtherObject
{
public function doSomethingElse() {
// Do something here
}
}
class MyObject implements MyObjectInterface
{
private $factory;
public function __construct(FactoryInterface $factory) {
$this->factory = $factory;
}
public function doSomething() {
$myOtherObject = $this->factory->create($name);
return 100 + $myOtherObject->doSomething();
}
}
$ factory是否需要被模拟,反过来我还需要MyOtherObject的嵌套模拟?
另一种方法是创建具体的类并在我的测试中传递它们吗?
答案 0 :(得分:1)
在这种情况下需要模拟工厂依赖性,因为似乎没有其他任何东西可以在不先模拟工厂的情况下进行测试。但测试用例的目的是测试工厂的create
方法是否被调用,或者可能是doSomething
合同的其他部分?
如果您想测试return
语句中发生的情况,可以将myOtherObject
的创建提取到方法中
public function createOtherObject($name)
{
return $this->factory->create($name);
}
现在您可以测试doSomething
的行为而无需模拟工厂(您可以简单地存根或覆盖createOtherObject
,如果您想测试工厂调用,那将是一个不同的测试,createOtherObject
)。
即使在这种简单的场景中,这样的重构也允许您根据需要模拟工厂及其创建的对象,而不是强迫两者都被模拟,即使您只是想测试return
行为。
除了这种可能性之外,假设您无论如何都需要测试一切,那么工厂及其创建将需要被模拟(或存根;通过"创建具体类"您可能意味着存根)。