typescript - 如何使用 jest 模拟构造函数实例化的 class 实例?

给定一个实例化并使用另一个 class Logger 的 class Person,如何在下面的示例中实例化 Person 时验证 Logger 的方法是否被调用?

// Logger.ts
export default class Logger {
    constructor() {}
    log(m: String) {
        console.log(m);

        // Other operations that are outside testing (e.g., file write).
        throw Error('error');
    }
}

// Person.ts
import Logger from "./Logger";
export default class Person {
    constructor() {
        const logger = new Logger();
        logger.log('created');
    }
    // ...
}

// Person.test.ts
import Person from "./Person";
import Logger from "./Logger";
describe('Person', () => {
    it('calls Logger.log() on instantiation', () => {
        const mockLogger = new Logger();
        getCommitLinesMock = jest
            .spyOn(mockLogger, 'log')
            .mockImplementation(() => {});

        new Person(); // Should call Logger.log() on instantiation.

        expect(getCommitLinesMock).toBeCalled();
    });
});

一种选择是将 Logger 作为构造函数参数传递,如下所示:

class Person {
    constructor(logger: Logger) {
        logger.log('created');
    }
    // ...
}

但是,有没有其他不改变构造函数来完成测试的方法呢?

回答1

您可以使用 https://jestjs.io/docs/jest-object#jestmockmodulename-factory-options 它会自动模拟给定模块的所有导出。

所以你可以做 jest.mock("./Logger")Logger 构造函数,它的所有方法都将被模拟函数替换(默认返回 undefined ),现在你可以监视构造函数及其所有方法的行为。

import Person from "./Person";
import Logger from "./Logger";

jest.mock("./Logger");

describe("Person", () => {
  it("calls the Logger constructor on instantiation", () => {
    new Person();
    expect(Logger).toHaveBeenCalledTimes(1);
  });
});

所有模拟函数都有一个特殊的 .mock 属性,其中可以使用与模拟函数相关的各种数据,包括模拟构造函数在使用 new 调用时创建的实例。

因此,模拟 Logger 创建的所有实例都保存在 Logger.mock.instances 中,您可以使用它来监视方法调用。

import Person from "./Person";
import Logger from "./Logger";

jest.mock("./Logger");

describe("Person", () => {
  it("calls the Logger constructor and the log method on instantiation", () => {
    new Person();
    expect(Logger).toHaveBeenCalledTimes(1);
    const mockLoggerInstance = Logger.mock.instances[0];
    const mockLogMethod = mockLoggerInstance.log;
    expect(mockLogMethod).toHaveBeenCalledTimes(1);
  });
});

相似文章

最新文章