typescript 如何在jest中的构造函数上示例化spyOn类

m0rkklqb  于 2022-12-05  发布在  TypeScript
关注(0)|答案(1)|浏览(157)

我有下一个代码:

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);
  }

我希望测试loginFunnel是否在状态为挂起时调用,服务是否在paramA时调用,但此类在构造函数中初始化:

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

那么我怎么能用笑话来监视呢?,这只是javascript,而不是React或类似的。
我尝试了很多东西,但我不知道如何...
最后一次尝试是这样的,从他的路径导入Tracker类......

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

但我从测验中得到了这样的答案:

expect(received).toHaveBeenCalledTimes(expected)

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

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

6jjcrrmo1#

我明白你的意思。它很复杂,我最后创建了这个代码片段,它可以监视整个类,包括它的构造函数。它的用法也很简单,你可以把这个片段添加到一个文件中,然后在需要的时候导入它。
下面是代码(typescript/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 };
    });
}

用法示例:

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();
});

希望它能对你和其他人有所帮助。

相关问题