typescript 如何使用jest模拟一个构造函数示例化的类示例?

p4tfgftt  于 2023-04-13  发布在  TypeScript
关注(0)|答案(2)|浏览(185)

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

// 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');
    }
    // ...
}

但是,有没有其他方法可以在不改变构造函数的情况下完成测试?

hgtggwj0

hgtggwj01#

您可以使用jest.mock(moduleName,factory,options),它将自动模拟给定模块的所有导出。
所以你可以做jest.mock("./Logger")Logger构造函数,它的所有方法都将被mock函数(* 默认返回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函数都有一个特殊的.mock属性,其中包含了与mock函数相关的各种数据,包括mock构造函数在使用new调用时创建的示例。
因此,mock 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);
  });
});
wrrgggsh

wrrgggsh2#

另一种用方法测试类的方法是在mockprototype中使用。

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

jest.mock("./Person");

describe("Person", () => {

 it("mock and test Person method", async () => {

  jest.spyOn(Person.prototype, "somePersonMethod").mockImplementation(() => {
      return "testing Person class method";
   });
    
    //expect(...

 });

});

相关问题