我正在为一个公共方法编写单元测试,而该方法又调用了用typescript(Node JS)编写的类的私有方法。
示例代码
class A {
constructor() {
}
public method1() {
if(this.method2()) {
// Do something
} else {
// Do something else
}
}
private method2() {
return true;
}
}
现在测试method1()我需要stub方法2()这是一个私有方法。
在这里我正在尝试:
sinon.stub(A.prototype, "method2");
Typescript抛出错误:
Argument of type '"method2"' is not assignable to parameter of type '"method1"'
任何帮助将不胜感激。 谢谢
答案 0 :(得分:9)
问题是sinon
的定义对stub
函数使用以下定义:
interface SinonStubStatic { <T>(obj: T, method: keyof T): SinonStub; }
这意味着第二个参数必须是T
类型的成员(公共成员)的名称。这通常是一个很好的限制,但在这种情况下,它有点过于严格。
您可以通过转换为any
:
sinon.stub(A.prototype, <any>"method2");
答案 1 :(得分:0)
有时候,当代码和测试的复杂性变得更加重要时,我倾向于将外部方法“外部化”。您可以通过(部分)类或(部分)接口来做到这一点。
it('private methods test', async () => {
// original class
class A{
public method1():string{
if(this.method2()) {
// Do something
return "true";
} else {
// Do something else
return "false";
}
}
// with private method
private method2():boolean{
return true;
}
}
// interface that makes the private method public
interface IAExternalized{
method2():boolean;
}
// class that makes the private method public
class APrivate implements IAExternalized{
// with public method
method2():boolean{
return true;
};
}
// test before mocking
let test:A = new A();
let result:string = test.method1();
result.should.be.equal("true");
// let's mock the private method, but with typechecking available
let stubMethod2:sinon.SinonStub = sinon.stub(<IAExternalized><unknown>(A.prototype), "method2").returns(false);
result = test.method1();
result.should.not.be.equal("true");
result.should.be.equal("false");
// access private method of an object through public-interface
let testPrivate:IAExternalized = <IAExternalized><unknown>test;
let result2:boolean = testPrivate.method2();
result2.should.not.be.equal(true);
result2.should.be.equal(false);
});
注意:如果您控制要测试的代码,则无需重复代码,容易出错,但是可以使您的类实现该接口。要将标准(无私有)接口转换为“外部”,可以使用公共方法进行扩展。
export interface IAExternalized extends IAPrivate {
method2():boolean
};