对于测试能力,我们避免使用" new"并使用依赖注入。怎么样" new"在对象的方法论证中?

时间:2015-09-12 06:26:59

标签: php unit-testing mocking phpunit tdd

我理解易于测试/模拟:

self.longPressPan.minimumPressDuration = 0.3

使用依赖注入,我理解 IS 现在很容易测试/模拟:

public function index(){

    $jedi = new Jedi(); // <-- "new" operator used here

    ...
}

但方法参数是否重要?请考虑下面的代码,是否也可以轻松测试/模拟?

public function index(JediInterface $jedi){

    $jedi->doSomething();

    ...
}

注意: $ jedi类具有方法定义:
public function index(JediInterface $jedi){ $jedi->setLightSaber(new BlueLightsaber()); // <-- "new" operator used in argument return $jedi->getLightsaberColor(); }

3 个答案:

答案 0 :(得分:1)

不,因为该对象是在mehod内部创建的。想象一下,你如何用一个使用index()的不同程序将BlueSaber替换为ChainSaw?

答案 1 :(得分:1)

它会影响可测试性。也许不是在中间,但是当你需要根据军刀颜色测试一些不同的物体时(这里它总是蓝色而且你不能改变它)。你可以争辩说,在这个没有发生的确切例子中,但总的来说,它会。

此外,也许将来你想改变BlueLightsaber的工作方式,所以它会在创建时记录一些信息。如果你不能嘲笑它,那么在测试时就会写出真实的日志。

有很多原因。学习它们的越来越好的方法是尝试测试受直接对象实例化困扰的遗留代码。

答案 2 :(得分:1)

如果BlueLightSaber的构造函数具有绝对没有副作用,并且您不会在不久的将来看到光剑的类型发生变化,我会保持您的实施方式它是。添加间接总是会带来额外的复杂性。

至于可测试性,您现在正在测试Jedi是否与BlueLightSaber一起正常工作(即您正在编写集成测试而不是仅针对jedi的隔离测试),但这不是一个问题本身。虽然确实当集成测试失败时,确定问题将更加困难,如果光剑确实是绝地的实现细节,那么你可能更好地编写集成测试。当他们对实现细节了解太多时,孤立的测试往往会妨碍未来的重构。

(有关隔离与综合测试的更多信息here

值得一提的另一点是:您正在将查询(获取光剑颜色)与在单个方法调用中更改状态(设置光标)的逻辑混合在一起。对于使用您的代码的开发人员来说,这可能会让人感到困惑,并且为了更好的理该原则称为Command-Query Separation(CQS)。此外,我倾向于尽可能避免更改输入参数(jedi)的状态,因为它可能导致与违反CQS相同的混乱错误。