我已经测试了您的代码,似乎使用 jest.mock 存在多个问题。
为了正确模拟模块,您必须在导入它之前先模拟它。这是一种内部机制(jest 如何模拟模块),您必须遵循此规则。
const logger = {
debug: jest.fn(),
log: jest.fn()
};
// IMPORTANT First mock winston
jest.mock("winston", () => ({
format: {
colorize: jest.fn(),
combine: jest.fn(),
label: jest.fn(),
timestamp: jest.fn(),
printf: jest.fn()
},
createLogger: jest.fn().mockReturnValue(logger),
transports: {
Console: jest.fn()
}
}));
// IMPORTANT import the mock after
import * as winston from "winston";
// IMPORTANT import your service (which imports winston as well)
import { LoggingService } from "../logger/logger.service";
正如您所看到的,您不能使用 Winston 实例作为模拟的返回值,但不用担心,也可以模拟该实例。 (您也可以在前面的代码示例中看到它)
const logger = {
debug: jest.fn(),
log: jest.fn()
};
最后,您不需要监视曾经模拟过的内容,因此只需直接询问模拟即可。
完整的代码在这里:
const logger = {
debug: jest.fn(),
log: jest.fn()
};
// trying to mock createLogger to return a specific logger instance
jest.mock("winston", () => ({
format: {
colorize: jest.fn(),
combine: jest.fn(),
label: jest.fn(),
timestamp: jest.fn(),
printf: jest.fn()
},
createLogger: jest.fn().mockReturnValue(logger),
transports: {
Console: jest.fn()
}
}));
import * as winston from "winston";
import { LoggingService } from "./logger.service";
describe("-- Logging Service --", () => {
let loggerMock: winston.Logger;
test("testing logger log function called...", () => {
const mockCreateLogger = jest.spyOn(winston, "createLogger");
const loggingService: LoggingService = LoggingService.Instance;
loggerMock = mockCreateLogger.mock.instances[0];
expect(loggingService).toBeInstanceOf(LoggingService);
expect(loggingService).toBeDefined();
expect(mockCreateLogger).toHaveBeenCalled();
// spy on the winston.Logger instance within this test and check
// that it is called - this is working from within the test method
logger.log("debug", "test log debug");
expect(logger.log).toHaveBeenCalled();
// now try and invoke the logger instance indirectly through the service class
// check that loggerMock is called a second time - this fails, only called once
// from the preceding lines in this test
loggingService.debug("debug message");
expect(logger.debug).toHaveBeenCalledTimes(1); // <- here
});
});
我将最后的断言更改为一,因为我调用了log
在测试中,并且debug
在日志服务中。
这是我使用的记录器服务:
import * as winston from "winston";
export class LoggingService {
logger: winston.Logger;
static get Instance() {
return new LoggingService();
}
constructor() {
this.logger = winston.createLogger();
}
debug(message: string) {
this.logger.debug(message);
}
}
玩得开心!