如何在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. 将测试代码本身放入闭包中,或在闭包中添加代码,该闭包存储对外部作用域中现有对象上的局部变量的引用.

    稍后,使用工具取出测试代码.

如果你做了什么,请给我一个更好的方法来解决这个问题?

附笔

  1. 对于类似类型的问题,像这样的问题,大多数答案并没有给出问题的解决方案,这就是为什么我要问这个问题

  2. 大多数开发者说你不测试私有函数,但我不说它们是错的或对的,但我的 case 有必要测试私有函数.

推荐答案

我同意你的观点,尽管"只对公共API进行单元测试"是一个很好的目标,但有时它似乎并没有那么简单,你会觉得自己在牺牲API或单元测试之间做出 Select .你已经知道这一点了,因为这正是你要求做的,所以我不想插手.:)

在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没有私有成员,因为这在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
    

    这显然会增加重构的难度.

  2. 您可以使用数组访问([])访问私有成员:

    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",让你在不失go 类型安全的情况下访问私有成员.这正是我认为你想要的单元测试.

这是working example in the TypeScript Playground美元.

Edit for TypeScript 2.6

有些人喜欢的另一个选项是使用// @ts-ignore(added in TS 2.6),它只会 suppress 以下行中的所有错误:

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

问题是,它会 suppress 以下行中的所有错误:

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

我个人认为@ts-ignore的代码气味,正如doctor 说:

我们建议您使用此注释very sparingly.[强调原文]

Typescript相关问答推荐

如何在类型脚本中声明对象其键名称不同但类型相同?

动态判断TypScript对象是否具有不带自定义类型保护的键

属性的类型,该属性是类的键,其值是所需类型

更新为Angular 17后的可选链运算符&?&问题

React重定向参数

如何重构长联合类型?

<;T扩展布尔值>;

我可以以这样一种方式键入对象,只允许它的键作为它的值吗?

对未到达受保护路由的路由环境做出react

Select 下拉菜单的占位符不起作用

已解决:如何使用值类型限制泛型键?

如何合并两个泛型对象并获得完整的类型安全结果?

Angular material 无法显示通过API获取的数据

类型实例化过深,可能是无限的&TypeScrip中的TupleUnion错误

TaskListProps[]类型不可分配给TaskListProps类型

顶点堆叠的图表条形图未在正确的x轴上显示

递归类型别名的Typescript 使用

定义一个只允许来自另一个类型的特定字符串文字的类型的最佳方式

如何按成员资格排除或 Select 元组?

使用本机 Promise 覆盖 WinJS Promise 作为 Chrome 扩展内容脚本?