如何使用 Jasmine 为私有方法编写 Angular / TypeScript 单元测试

新手上路,请多包涵

您如何在 angular 2 中测试私有函数?

 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;
    }

}

我找到的解决方案

  1. 将测试代码本身放在闭包内或在闭包内添加代码,该闭包存储对外部范围内现有对象的局部变量的引用。

稍后使用工具剥离测试代码。 http://philipwalton.com/articles/how-to-unit-test-private-functions-in-javascript/

如果您做过任何事情,请建议我一个更好的方法来解决这个问题?

附言

  1. 大多数类似问题的答案都没有解决问题,这就是我问这个问题的原因

  2. 大多数开发人员都说你不要测试私有函数,但我没有说它们是对还是错,但是我的案例有必要测试私有。

原文由 tymspy 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 1.1k
2 个回答

我支持你,尽管“仅对公共 API 进行单元测试”是一个很好的目标,但有时它看起来并不那么简单,你觉得你在妥协 API 或单元测试之间做出选择。你已经知道了,因为这正是你要求做的,所以我不会进入它。 :)

在 TypeScript 中,我发现了一些可以访问私有成员以进行单元测试的方法。考虑这个类:

 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 使用 privateprotectedpublic 限制对类成员的访问,编译的 JS 中没有私有成员,因为这不是’ .它纯粹用于 TS 编译器。为此:

  1. 您可以断言 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

这显然会使重构更加困难。

  1. 您可以使用数组访问( [] )来获取私有成员:
    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

老实说,我不知道为什么会这样。这显然是一个 故意的“逃生舱” ,让您可以在不失去类型安全的情况下访问私人成员。这正是我认为你想要的单元测试。

这是 TypeScript Playground 中的一个工作示例

编辑 TypeScript 2.6

有些人喜欢的另一个选项是使用 // @ts-ignore在 TS 2.6 中添加),它简单地抑制了以下行中的所有错误:

 // @ts-ignore
thing._name = "Unit Test";

这样做的问题是,它抑制了以下行中的所有错误:

 // @ts-ignore
thing._name(123).this.should.NOT.beAllowed("but it is") = window / {};

我个人认为 @ts-ignore 一种代码气味,正如文档所说:

我们建议您 非常谨慎地 使用此评论。 【重点原创】

原文由 Aaron Beall 发布,翻译遵循 CC BY-SA 4.0 许可协议

这对我有用:

代替:

 sut.myPrivateMethod();

这个:

 sut['myPrivateMethod']();

原文由 brainmonger 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进