【发布时间】:2020-07-31 06:34:57
【问题描述】:
我正在努力寻找在测试日志服务中模拟和使用 pino 的正确方法, 所以这是我对 pino 记录器的实现。这会根据日志级别写入不同的文件流。
getChildLoggerService(fileNameString): pino.Logger {
const streams: Streams = [
{ level: 'fatal', stream: fs.createWriteStream(path.join(process.cwd(), './logs/database-connect-fatal.log'))},
{ level: 'error', stream: fs.createWriteStream(path.join(process.cwd(), './logs/database-connect-error.log'))},
{ level: 'debug', stream: fs.createWriteStream(path.join(process.cwd(), './logs/database-connect-debug.log'))},
{ level: 'info', stream: fs.createWriteStream(path.join(process.cwd(), './logs/database-connect-info.log'))},
];
return pino({useLevelLabels: true,
base: {
hostName: os.hostname(),
platform: os.platform(),
processId: process.pid,
timestamp: this.appUtilService.getCurrentLocaleTimeZone(),
// tslint:disable-next-line: object-literal-sort-keys
fileName: this.appUtilService.getFileName(fileNameString),
} ,
level: this.appUtilService.getLogLevel(),
messageKey: LOGGER_MSG_KEY,
prettyPrint: this.appUtilService.checkForDevEnv(process.env.NODE_ENV),
timestamp: () => {
return this.appUtilService.getCurrentLocaleTimeZone()
},
}, multistream(streams)).child({
connectorReqId: (process.env.REQ_APP_NAME === null ? 'local': process.env.REQ_APP_NAME)
+uuid.v4().toString()
});
}
我想测试的最重要的部分是多流,我需要根据日志级别写入不同的日志文件,到目前为止我还想不出办法
import pino, { DestinationStream } from 'pino';
const sinon = require('sinon');
import pinoms from 'pino-multi-stream';
const fs = require('fs');
const path = require('path');
const stream = require('stream');
const { PassThrough } = require('stream');
class EchoStream extends stream.Writable {
_write(chunk, enc, next) {
console.log('ssdsdsd',chunk.toString());
next();
}
}
import * as _ from 'lodash';
import { Writable } from 'stream';
import { mocked } from 'ts-jest/utils';
import { LogServiceInstance } from './log.service';
// jest.mock('pino', () => jest.fn().mockImplementation(() => { ====> Tried this inline mock, doesnt work
// return {
// child: jest.fn().mockReturnValue(jest.requireActual('pino').Logger)
// }
// }));
// jest.mock('pino', () => {
// return jest.fn().mockImplementation(() => {
// return {
// child: jest.fn().mockReturnValue(jest.requireActual('pino').Logger),
// stream: jest.fn().mockImplementation(() => {
// return [
// {
// level: 'info',
// stream: fs.createWriteStream(
// path.resolve(process.cwd(), '/test/database-connector-logs/info.log')
// ),
// },
// {
// level: 'warn',
// stream: fs.createWriteStream(
// path.resolve(process.cwd(), '/test/database-connector-logs/warn.log')
// ),
// },
// ];
// }),
// };
// });
// });
describe('Test suite for Log service', () => {
//const mockedPino = mocked(pino, true);
test('Test case for getLoggerInstance', () => {
const mockedPinoMsStream = [
const mockedPinoStream = (pino.prototype.stream = jest.fn(() => mockedPinoMsStream));
console.dir(pino);
const prop = Reflect.ownKeys(pino).find((s) => {
return s === 'symbols';
});
// Tried this but it did not work as the actual files are written with the values
pino[prop]['streamSym'] = jest.fn().mockImplementation(() => {
return fs.createWriteStream(path.resolve(process.cwd(), './test/database-connector-logs/info.log'))
});
console.dir(pino);
const log = LogServiceInstance.getChildLoggerService(__filename);
console.dir(Object.getPrototypeOf(log));
log.info('test logging');
expect(2).toEqual(2);
});
有人可以告诉我模拟错误的地方以及如何正确模拟它
更新:
我开始明白模拟 pino-multi-stream 可能会奏效,所以尝试了这种方式。这是在最顶部添加的,其余的所有模拟都被删除(即使在测试套件中也是如此)
const mockedPinoMultiStream = {
stream: jest.fn().mockImplementation(() => {
return {write: jest.fn().mockReturnValue(new PassThrough())}
})
}
jest.mock('pino-multi-stream', () => {
return {
multistream: jest.fn().mockReturnValue(mockedPinoMultiStream)
}
});
想模拟测试是否基于级别,正在使用相应的命名文件,但这也会导致异常
TypeError: stream.write 不是函数
at Pino.write (/XXX/node_modules/pino/lib/proto.js:161:15)
at Pino.LOG (/XXXX/node_modules/pino/lib/tools.js:39:26)
最新更新:
所以我通过修改模拟 pino 多流的方式解决了异常
const { PassThrough } = require('stream');
...
...
const mockedPinoMultiStream = {
write: jest.fn().mockImplementation((data) => {
return new Passthrough();
})
};
现在不再有异常,并且当我打印“pino”时,write(method) 被正确地模拟了。但是我不明白如何根据不同的日志级别测试不同的文件。有人可以告诉我,这是怎么做的。? 注意:我尝试设置 fs.createWriteStream 的返回值而不是 Passthrough 但这不起作用
【问题讨论】:
标签: node.js typescript jestjs ts-jest