是否应该嘲笑简单的协作者/依赖者

时间:2016-04-17 16:22:31

标签: php unit-testing phpunit

何时嘲笑,何时不嘲笑。

如果我要在以下示例中为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的嵌套模拟?

另一种方法是创建具体的类并在我的测试中传递它们吗?

1 个答案:

答案 0 :(得分:1)

在这种情况下需要模拟工厂依赖性,因为似乎没有其他任何东西可以在不先模拟工厂的情况下进行测试。但测试用例的目的是测试工厂的create方法是否被调用,或者可能是doSomething合同的其他部分?

如果您想测试return语句中发生的情况,可以将myOtherObject的创建提取到方法中

public function createOtherObject($name)
{
    return $this->factory->create($name);
}

现在您可以测试doSomething的行为而无需模拟工厂(您可以简单地存根或覆盖createOtherObject,如果您想测试工厂调用,那将是一个不同的测试,createOtherObject)。

即使在这种简单的场景中,这样的重构也允许您根据需要模拟工厂及其创建的对象,而不是强迫两者都被模拟,即使您只是想测试return行为。

除了这种可能性之外,假设您无论如何都需要测试一切,那么工厂及其创建将需要被模拟(或存根;通过"创建具体类"您可能意味着存根)。