简体   繁体   English

如何在开玩笑的构造函数上实例化 class

[英]How to spyOn class instantiated on constructor in jest

I have the next code:我有下一个代码:

async function(paramA?: string): Promise<void> {
    if (paramA === undefined) {
      paramA = this.randomString();
    }
    this.funnel.loginFunnel(Status.Pending);
    await this.tracker.flush();
    this.service.call(this.name, paramA, code);
  }

And I want test that loginFunnel is called with status pending, and the service is call with the paramA, but this classes are initialized in constructor:我想测试 loginFunnel 被调用时状态未决,并且服务是用 paramA 调用的,但是这个类是在构造函数中初始化的:

constructor(params: Params) {
    this.tracker = new Tracker(params);
    this.service = new Service(params, this.tracker);
  }

So how I can spy on with jest?, this is only javascript, not React or similar.那么我怎么能开玩笑地监视呢?这只是 javascript,不是 React 或类似的。

I try a lot of things, but I don't know how do...我尝试了很多东西,但我不知道该怎么做...

The last try was this, import Tracker class from his path...最后一次尝试是这样的,从他的路径中导入 Tracker class ...

jest.mock('../tracker');
        service.call();
        expect(Tracker).toHaveBeenCalledTimes(1);

But I got this answer from test:但我从测试中得到了这个答案:

expect(received).toHaveBeenCalledTimes(expected)

    Matcher error: received value must be a mock or spy function

    Received has type:  function
    Received has value: [Function Tracker]

I understand your point.我明白你的意思。 It's complex and I ended up creating this code snippet, which can spyOn an entire class, including its constructors.它很复杂,我最终创建了这个代码片段,它可以监视整个 class,包括它的构造函数。 And the usage is also somehow simple, you can add this snippet to a file and import it whenever you need.而且用法也很简单,您可以将此代码段添加到文件中并在需要时导入它。

Here is the code (typescript/ES6):这是代码(打字稿/ES6):

/**
 * spyOn references to classes. Use it with spyOnClass
 */
export const classSpy: any = {};

/**
 * Utility to Spy On all class methods. Not including the constructor
 * @returns a spyOn references to all the class methods
 * includes the methods mockClear and mockReset as convenience
 * to trigger the respective method for all the spies
 */
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
export function spyOnClassMethods(proto: any): any {
    const properties = Object.getOwnPropertyNames(proto);
    const spyHolder: any = {};
    for (const i in properties) { spyHolder[properties[i]] = jest.spyOn(proto, properties[i]); }
    spyHolder.mockClear = (): void => { for (const i in properties) { spyHolder[properties[i]].mockClear(); } };
    spyHolder.mockReset = (): void => { for (const i in properties) { spyHolder[properties[i]].mockReset(); } };
    return spyHolder;
}
// To attend jest.mock problems, the should start with 'mock'
const mocksSpyOnClassMethods = spyOnClassMethods;

/**
 * Utility to Spy On all class methods and its constructor.
 */
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
export function spyOnClass(mockModuleName: string, mockClassName: string): any {
    classSpy[mockClassName] = {};
    jest.mock(mockModuleName, () => {
        const module = jest.requireActual(mockModuleName) as any;
        const mock = {};
        classSpy[mockClassName] = mocksSpyOnClassMethods(module[mockClassName].prototype);
        mock[mockClassName] = jest.fn().mockImplementation(
            (...args: any[]) => {
                const instance = new module[mockClassName](...args);
                classSpy[mockClassName].constructor = mock[mockClassName];
                return instance;
            }
        );
        return { ...module, ...mock };
    });
}

Usage example:使用示例:

import { classSpy, spyOnClass } from './mock-utils';

// If you import ClassName, this must come before the import.
spyOnClass('module-name', 'ClassName');

import { ClassName } from 'module-name';

test('this', () => {
    doSomethingThatUsesClassName();
    expect(classSpy.ClassName.constructor).toHaveBeenCalled();
    expect(classSpy.ClassName.someMethod).toHaveBeenCalled();
});

Hope it can help you and others.希望它可以帮助你和其他人。

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

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