如何使用 Jasmine 为私有方法编写 Angular/TypeScript 的单元测试 [英] How to write unit testing for Angular / TypeScript for private methods with Jasmine

查看:40
本文介绍了如何使用 Jasmine 为私有方法编写 Angular/TypeScript 的单元测试的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

How do you test a private function in 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. Put the test code itself inside the closure or Add code inside the closure that stores references to the local variables on existing objects in the outer scope.

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

Later strip out the test code using a tool. http://philipwalton.com/articles/how-to-unit-test-private-functions-in-javascript/

如果你有解决这个问题的方法,请给我建议一个更好的方法?

Please suggest me a better way to solve this problem if you have done any?

附言

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

  1. Most of the answer for similar type of question like this one doesn't give a solution to problem, that's why I'm asking this question

大部分开发者都说你不要测试私有函数,但我没有说它们是错的或对的,但是我的案例有必要测试私有.

Most of the developer say you Don’t test private functions but I don't say they are wrong or right, but there are necessities for my case to test private.

推荐答案

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

I'm with you, even though it's a good goal to "only unit test the public API" there are times when it doesn't seem that simple and you feel you are choosing between compromising either the API or the unit-tests. You know this already, since that's exactly what you're asking to do, so I won't get into it. :)

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

In TypeScript I've discovered a few ways you can access private members for the sake of unit-testing. Consider this class:

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 编译器.因此:

Even though TS restricts access to class members using private, protected, public, the compiled JS has no private members, since this isn't a thing in JS. It's purely used for the TS compiler. Therefor:

  1. 您可以对 any 进行断言并避免编译器警告您访问限制:

  1. You can assert to any and escape the compiler from warning you about access restrictions:

(thing as any)._name = "Unit Test";
(thing as any)._count = 123;
(thing as any).init("Unit Test", 123);

这种方法的问题在于,编译器根本不知道您对 any 在做什么,因此您不会得到所需的类型错误:

The problem with this approach is that the compiler simply has no idea what you are doing right of the any, so you don't get desired type errors:

(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

这显然会使重构变得更加困难.

This will obviously make refactoring more difficult.

您可以使用数组访问 ([]) 来获取私有成员:

You can use array access ([]) to get at the private members:

thing["_name"] = "Unit Test";
thing["_count"] = 123;
thing["init"]("Unit Test", 123);

虽然看起来很时髦,但 TSC 实际上会验证类型,就像您直接访问它们一样:

While it looks funky, TSC will actually validate the types as if you accessed them directly:

thing["_name"] = 123; // type error
thing["_count"] = "Unit Test"; // type error
thing["init"](0, "123"); // argument error

老实说我不知道​​为什么会这样.这显然是一个 有意的逃生舱口" 使您可以访问私人成员而不会失去类型安全性.这正是我认为您想要的单元测试.

To be honest I don't know why this works. This is apparently an intentional "escape hatch" to give you access to private members without losing type safety. This is exactly what I think you want for your unit-testing.

下面是一个了打字稿游乐场的工作实施例.

Here is a working example in the TypeScript Playground.

针对 TypeScript 2.6 进行编辑

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

Another option that some like is to use // @ts-ignore (added in TS 2.6) which simply suppresses all errors on the following line:

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

问题在于,它会抑制以下行中的所有错误:

The problem with this is, well, it suppresses all errors on the following line:

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

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

I personally consider @ts-ignore a code-smell, and as the docs say:

我们建议您非常谨慎地使用此评论.[强调原创]

we recommend you use this comments very sparingly. [emphasis original]

这篇关于如何使用 Jasmine 为私有方法编写 Angular/TypeScript 的单元测试的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆