如何在 Angular 2 中测试私有(private)函数?
class FooBar {
private _status: number;
constructor( private foo : Bar ) {
this.initFooBar();
}
private initFooBar(){
this.foo.bar( "data" );
this._status = this.fooo.foo();
}
public get status(){
return this._status;
}
}
我找到的解决方案
将测试代码本身放入闭包内或将代码添加到闭包内,闭包存储对外部作用域中现有对象的局部变量的引用。
稍后使用工具剥离测试代码。 http://philipwalton.com/articles/how-to-unit-test-private-functions-in-javascript/
如果你做过,请给我一个更好的方法来解决这个问题?
附言
大多数类似问题的答案都没有给出问题的解决方案,这就是我问这个问题的原因
大多数开发者都说你不要测试私有(private)函数,但我不说他们是错的还是对的,但我的案例有测试私有(private)的必要性。
最佳答案
我同意你的看法,尽管“只对公共(public) API 进行单元测试”是一个很好的目标,但有时它看起来并不那么简单,你觉得你在妥协 API 或单元之间做出选择-测试。您已经知道这一点,因为这正是您要执行的操作,所以我不会深入探讨。 :)
在 TypeScript 中,为了进行单元测试,我发现了几种访问私有(private)成员的方法。考虑这个类:
class MyThing {
private _name:string;
private _count:number;
constructor() {
this.init("Test", 123);
}
private init(name:string, count:number){
this._name = name;
this._count = count;
}
public get name(){ return this._name; }
public get count(){ return this._count; }
}
即使 TS 使用 private
、protected
、public
限制对类成员的访问,编译后的 JS 没有私有(private)成员,因为这是不是 JS 的东西。它纯粹用于 TS 编译器。为此:
您可以对
any
断言并避免编译器向您发出有关访问限制的警告:(thing as any)._name = "Unit Test"; (thing as any)._count = 123; (thing as any).init("Unit Test", 123);
这种方法的问题是编译器根本不知道你在做什么
any
,所以你不会得到期望的类型错误:(thing as any)._name = 123; // wrong, but no error (thing as any)._count = "Unit Test"; // wrong, but no error (thing as any).init(0, "123"); // wrong, but no error
这显然会使重构变得更加困难。
您可以使用数组访问 (
[]
) 获取私有(private)成员:thing["_name"] = "Unit Test"; thing["_count"] = 123; thing["init"]("Unit Test", 123);
虽然看起来很时髦,但 TSC 实际上会像您直接访问它们一样验证类型:
thing["_name"] = 123; // type error thing["_count"] = "Unit Test"; // type error thing["init"](0, "123"); // argument error
老实说,我不知道为什么会这样。这显然是一个 intentional "escape hatch"让您在不失去类型安全的情况下访问私有(private)成员。这正是我认为您想要的单元测试。
这是一个working example in the TypeScript Playground .
为 TypeScript 2.6 编辑
有些人喜欢的另一种选择是使用 //@ts-ignore
( added in TS 2.6 ),它可以简单地抑制以下行中的所有错误:
// @ts-ignore
thing._name = "Unit Test";
这个问题是,好吧,它抑制了以下行中的所有错误:
// @ts-ignore
thing._name(123).this.should.NOT.beAllowed("but it is") = window / {};
我个人认为 @ts-ignore
是一种代码味道,正如文档所说:
we recommend you use this comments very sparingly. [emphasis original]
关于angular - 如何使用 Jasmine 为私有(private)方法编写 Angular/TypeScript 的单元测试,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35987055/