我们有一个简单的快速应用程序。我们使用温斯顿作为第三方,以便能够正确处理日志记录。
const express = require('express');
const app = express();
const { createLogger, transports } = require('winston');
const port = process.env.PORT || 5000;
const logger = createLogger({ transports: [ new transports.Console()] });
const { catchAll } = require('./routes/catchall');
app.get('*', catchAll);
app.listen(port, () => logger.log({ level: 'info', message: `server listening on port ${port}!` }));
我们希望,在我们的单元测试中,检查 createLogger 是否已使用正确的参数调用。
我们首先尝试只是使用jest.mock('winston)
但开玩笑地抱怨TypeError: transports.Console is not a constructor
。
然后,我们尝试使用以下方法手动模拟包:
let { createLogger, transports } = require('winston');
const consoleClass = class Console{};
jest.doMock('winston', () => {
return {
createLogger: jest.fn(),
transports: {
Console: consoleClass
}
}
});
describe('logger', () => {
it('should create proper logger', () => {
expect(createLogger).lastCalledWith({ transports: [ new transports.Console()] })
});
});
有关控制台的错误消失了。但是我们的测试失败了:
logger › should create proper logger
expect(jest.fn())[.not].lastCalledWith()
jest.fn() value must be a mock function or spy.
Received:
function: [Function anonymous]
39 | describe('logger', () => {
40 | it('should create proper logger', () => {
> 41 | expect(createLogger).lastCalledWith({ transports: [ new transports.Console()] })
| ^
42 | });
43 | });
44 |
at Object.lastCalledWith (tests/app.spec.js:41:26)
我们试图在doMock
后添加
createLogger.mockImplementation(() => {});
但它抱怨说TypeError: createLogger.mockImplementation is not a function
我们如何替换传输属性和创建记录器?
我们需要能够模拟createLogger
的实现,然后能够在另一个测试中断言app.listen
已被使用记录器.log和适当的参数调用。
尝试以下方法:
const mockCreateLogger = jest.fn().mockImplementation(() => {
log: jest.fn()
});
const mockConsole = jest.fn().mockImplementation(() => () => {});
jest.mock('winston', () => ({
createLogger: mockCreateLogger, // name must start with mock prefix
transports: {
Console: mockConsole // name must start with mock prefix
}
}));
// here import the file you are testing after the mocks
describe('logger', () => {
it('should create proper logger', () => {
expect(mockCreateLogger).toHaveBeenCalledWith({ transports: expect.anything() })
});
});
附言为了在这里正确编写单元测试,您还应该模拟express
以便处理模拟app
而不是导入"真实"的表达式