简体   繁体   English

如何模拟使用ts Mockito在Typescript中的另一个类中初始化的类方法?

[英]How to mock a class method's which is initialized inside another class in typescript using ts mockito?

This is my Class I want to test using mocha-chai test framework in typescript. 这是我要在打字稿中使用mocha-chai测试框架进行测试的班级。 I am using ts-mockito for mocking. 我正在使用ts-mockito进行模拟。

export class ClassA implements IClassA {

    private classAResource: IClassAResource;

    constructor(){
         this.classAResource= new ClassAResource();
    }

    public async cancel(jobid){
       const job = this.classAResource.getJob(jobid);
       //cancel logic
    }
}

ClassAResource class looks like this, ClassAResource类看起来像这样,

export class StreamResource implements IStreamResource {

private jobs: Map<string, Job>;

 constructor(){
 this.jobs= new Map();
 }

public async createJob(): Promise<Job> {
//add the job to map
}

public async getJob(jobid): Promise<Job>{
//return the specified job item from map
}


}

In my test I try to mock ClassAResource's getJob method like this, 在我的测试中,我尝试像这样模拟ClassAResource的getJob方法,

const classAResource: IClassAResource = new ClassAResource ();
 const classAResourceSpy = spy(classAResource);

 when(classAResourceSpy.getJob(anyString())).thenResolve(job); 

And I call the ClassA cancel method like this, 我这样调用ClassA cancel方法,

classA.cancel(jobid)

I expect the getJob call in cancel method to be mocked and return a job object. 我希望对cancel方法中的getJob调用进行模拟并返回作业对象。

But the test is not behaving according to my expectation. 但是测试没有按照我的预期进行。 Mock doesnt come into picture and getJob() goes to actual implementation and return undefined. 模拟不会出现,并且getJob()进入实际实现并返回未定义。

I read online, this issue is because of the constructor initializations in ClassAResource class. 我在网上阅读,这个问题是由于ClassAResource类中的构造函数初始化引起的。

I removed the constructor and tried and now the getJob mock works. 我删除了构造函数并尝试过,现在getJob模拟工作了。

But I need the constructor to instantiate the map object and ability to maintain the jobs. 但是我需要构造函数实例化map对象和维护作业的能力。

Is there some workaround through which I can mock getJob() with constructor in place? 有一些变通办法,可以通过它在构造函数到位的情况下模拟getJob()吗?

Am I doing something wrong here? 我在这里做错什么了吗?

I am kind of relatively new to typescript and ts-mockito and any help is greatly appreciated. 我对打字稿和ts-mockito还是比较陌生,对您的帮助非常感谢。

This really has nothing to do with TypeScript specifically, but rather a testability issue due to breaking the Dependency Inversion principle . 实际上,这确实与TypeScript无关,而是由于违反了Dependency Inversion原理而导致的可测试性问题。
Instantiating members in the constructor of the class causes a testability issue, since the control over the instantiation is in the hands of the code under test (aka "unit under test", "class under test", etc.). 在类的构造函数中实例化成员会导致可测试性问题,因为对实例化的控制权在被测代码(也称为“被测单元”,“被测类”等)的手中。 That means, that you have little to no control over which instance the class you're testing will have. 这意味着,您几乎无法控制要测试的类具有哪个实例。

There are some mocking libraries that allow a "hostile takeover" of the instantiation of certain classes (at least for Java, see PowerMock ), but they should be used very sparingly, if at all, since they contribute to perpetuating the lack of testability. 有一些模拟库允许某些类的实例的“恶意接管”(至少对于Java,请参阅PowerMock ),但是应该使用它们(如果有的话)非常谨慎,因为它们会导致缺乏可测试性。

Instead of instantiating IClassAResource from the constructor of ClassA , you should either get the instance via injection (DI, constructor, setter method, etc.), or at least use a factory/builder. 代替从ClassA的构造函数实例化IClassAResource ,您应该通过注入(DI,构造函数,setter方法等)获取实例,或者至少使用工厂/构造器。 This way your class would become testable and your design will be improved. 这样,您的班级将成为可测试的,并且您的设计将得到改善。

In general, you should adhere to all of the SOLID principles, since they are, at least at the moment, considered the most accurate and concise set of good OOP design principles. 通常,您应该遵守所有SOLID原则,因为至少在目前,它们被认为是最准确,最简洁的一组良好的OOP设计原则。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM