单元测试私有方法

5
在TypeScript中,测试私有方法的最佳方法是什么?在测试AngularJS控制器时,有时控制器会向$scope添加属性(函数),如果我不将该属性公开并分配给$scope,则可能无法对其进行测试。是否有推荐的方法。
export class MyCtrl{
    constructor($scope){
        $scope.addProp = (d:string) => {
            this.addProp();
        }
    }

    private addProp(){
        //...
    }
}
3个回答

7
一种解决方案是重新架构您的代码,使其更易于测试。 您可以创建一个AddPropProvider执行实际工作(实现细节更暴露以进行测试),并将其传递给MyCtrl的构造函数。 这是典型的控制反转策略。
另一种解决方案可能是将该函数改为public? 私有函数适用于隐藏可能会更改的实现细节,但也许您知道该函数始终存在。
最后还有一个hack方法。 该函数确实存在于MyCtrl实例中,但编译器不希望您调用它,因为您这样说了。
var m = new MyCtrl();
(<any>m).addProp();

现在,如果您删除或修改addProp的签名,该代码仍将编译,因此您已失去了类型安全性。在大多数代码中,这是不好的。但是,这是单元测试代码,所以我们将学习如何早期和轻松地进行故障检测,因此它并不可怕。

1
我不认为推广这种解决方案是好的。人们有意使某些东西保密。通过欺骗编译器来削弱这一点,忽略了沟通并削弱了类作者删除私有方法的能力。最好的做法是直接删除 private 修饰符并清楚地表明它不再是私有的。 - Jeff May
2
单元测试并不是铁板钉钉的。当实现发生变化时,它们经常需要更改。避免这种情况的方法是编写功能测试。 - Jeffery Grajkowski
1
是的。重写单元测试非常普遍,但您不应该接受这种命运。编写良好的测试应该能够随着您的代码进行重构而不会出错。根据名称属性强制转换为任何类型并引用属性是 TypeScript 允许开发人员避免的一种脆弱和令人困惑的方法。我认为它更像是一种反模式。 - Jeff May

1
虽然我同意Jeffery Grajkowski提出的解决方案,但还有一个选项需要考虑。由于JavaScript(以及扩展的TypeScript)没有“真正”的私有类型,因此将其公开,但按照惯例保持私有。
也就是说,方法名称应以下划线或“unitTest”开头,这样任何看到它的人都会认识到它不应在生产代码中使用。

1
一种解决方案是不将作用域作为UI的强粘合剂,而只将其用作控制器类实例的容器。这也有其他优点http://www.youtube.com/watch?v=WdtVn_8K17E 然后,您可以像测试任何其他JavaScript类一样简单地测试您的控制器,并且不必在测试中担心$scope。

1
我喜欢这个解决方案,因为它符合Angular添加模型对象而不是模型字段到控制器作用域的最佳实践。你发布的视频展示了直接绑定字段带来的一些麻烦。 - Jeff May

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接