如何在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;
    }

}

我找到了解决办法

将测试代码本身放在闭包中,或者在闭包中添加代码,以存储外部作用域中现有对象上局部变量的引用。 稍后使用工具提取测试代码。 http://philipwalton.com/articles/how-to-unit-test-private-functions-in-javascript/

如果你做过这个问题,请给我一个更好的解决方法。

P.S

大多数类似类型的问题的答案都没有给出问题的解决方案,这就是我问这个问题的原因 大多数开发人员说不要测试私有函数,但我不会说它们是错的还是对的,但我的案例中有必要测试私有函数。


当前回答

由于大多数开发人员不建议测试私有函数,为什么不测试它呢?

Eg.

YourClass.ts

export class FooBar {
  private _status: number;

  constructor( private foo : Bar ) {
    this.initFooBar({});
  }

  private initFooBar(data){
    this.foo.bar( data );
    this._status = this.foo.foo();
  }
}

TestYourClass.spec.ts

describe("Testing foo bar for status being set", function() {

...

//Variable with type any
let fooBar;

fooBar = new FooBar();

...
//Method 1
//Now this will be visible
fooBar.initFooBar();

//Method 2
//This doesn't require variable with any type
fooBar['initFooBar'](); 
...
}

感谢@Aaron, @Thierry Templier。

其他回答

我采用的这种方法是在类外部创建函数,并将函数分配给我的私有方法。

export class MyClass {
  private _myPrivateFunction = someFunctionThatCanBeTested;
}

function someFunctionThatCanBeTested() {
  //This Is Testable
}

现在我不知道我破坏了哪种类型的OOP规则,但是为了回答这个问题,这是我测试私有方法的方法。我欢迎任何人就利弊提出建议。

你可以调用私有方法!

如果您遇到以下错误:

expect(new FooBar(/*...*/).initFooBar()).toEqual(/*...*/)
// TS2341: Property 'initFooBar' is private and only accessible within class 'FooBar'

只需使用// @ts-ignore:

// @ts-ignore
expect(new FooBar(/*...*/).initFooBar()).toEqual(/*...*/)

感谢@Moff452的评论。你也可以这样写:

expect(new FooBar(/*...*/)['initFooBar']()).toEqual(/*...*/)

更新:

@ts-expect-error是@ts-ignore的更好选择。看到的: https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-9.html#ts-ignore-or-ts-expect-error

由于大多数开发人员不建议测试私有函数,为什么不测试它呢?

Eg.

YourClass.ts

export class FooBar {
  private _status: number;

  constructor( private foo : Bar ) {
    this.initFooBar({});
  }

  private initFooBar(data){
    this.foo.bar( data );
    this._status = this.foo.foo();
  }
}

TestYourClass.spec.ts

describe("Testing foo bar for status being set", function() {

...

//Variable with type any
let fooBar;

fooBar = new FooBar();

...
//Method 1
//Now this will be visible
fooBar.initFooBar();

//Method 2
//This doesn't require variable with any type
fooBar['initFooBar'](); 
...
}

感谢@Aaron, @Thierry Templier。

这招对我很管用:

而不是:

sut.myPrivateMethod();

这样的:

sut['myPrivateMethod']();

Aaron的答案是最好的,对我来说也很有用:) 我会给它投票,但遗憾的是我不能(失去声誉)。

我不得不说,测试私有方法是使用它们并在另一方面有干净代码的唯一方法。

例如:

class Something {
  save(){
    const data = this.getAllUserData()
    if (this.validate(data))
      this.sendRequest(data)
  }
  private getAllUserData () {...}
  private validate(data) {...}
  private sendRequest(data) {...}
}

不一次测试所有这些方法是很有意义的,因为我们需要模拟出那些私有方法,我们不能模拟出来,因为我们不能访问它们。这意味着我们需要对一个单元测试进行大量的配置,以将其作为一个整体进行测试。

这就是说,测试上述方法的所有依赖关系的最佳方法是端到端测试,因为这里需要集成测试,但如果您正在实践TDD(测试驱动开发),则端到端测试对您没有帮助,但测试任何方法都有帮助。