首先,我是 es6
和 jest
的新手。
我有一个用于实例化 winston
的 Logger
类,我想测试它。
这里是我的代码:
const winston = require('winston');
const fs = require('fs');
const path = require('path');
const config = require('../config.json');
class Logger {
constructor() {
Logger.createLogDir(Logger.logDir);
this.logger = winston.createLogger({
level: 'info',
format: winston.format.json(),
transports: [
new (winston.transports.Console)({
format: winston.format.combine(
winston.format.colorize({ all: true }),
winston.format.simple(),
),
}),
new (winston.transports.File)({
filename: path.join(Logger.logDir, '/error.log'),
level: 'error',
}),
new (winston.transports.File)({
filename: path.join(Logger.logDir, '/info.log'),
level: 'info',
}),
new (winston.transports.File)({
filename: path.join(Logger.logDir, '/combined.log'),
}),
],
});
}
static get logDir() {
return (config.logDir == null) ? 'log' : config.logDir;
}
static createLogDir(logDir) {
if (!fs.existsSync(logDir)) {
// Create the directory if it does not exist
fs.mkdirSync(logDir);
}
}
}
exports.logger = new Logger().logger;
export default new Logger();
我想测试我的函数 createLogDir()
。
我的想法是,我认为测试 fs.existsSync 的状态是个好主意。
如果 fs.existsSync
返回 false
,则必须调用 fs.mkdirSync
。
所以我试着写一些 jest
测试:
describe('logDir configuration', () => {
test('default path must be used', () => {
const logger = require('./logger');
jest.mock('fs');
fs.existsSync = jest.fn();
fs.existsSync.mockReturnValue(false);
const mkdirSync = jest.spyOn(logger, 'fs.mkdirSync');
expect(mkdirSync).toHaveBeenCalled();
});
});
但是,我遇到了一个错误:
● logDir configuration › default path must be used
Cannot spy the fs.mkdirSync property because it is not a function; undefined given instead
18 | fs.existsSync = jest.fn();
19 | fs.existsSync.mockReturnValue(true);
> 20 | const mkdirSync = jest.spyOn(logger, 'fs.mkdirSync');
21 | expect(mkdirSync).toHaveBeenCalled();
22 | });
23 | });
at ModuleMockerClass.spyOn (node_modules/jest-mock/build/index.js:590:15)
at Object.test (src/logger.test.js:20:28)
你能帮我调试和测试我的功能吗?
问候。
最佳答案
出现此错误是因为它在您的 logger
对象上寻找一个名为 fs.mkdirSync
的方法,但该方法不存在。如果您可以在测试中访问 fs
模块,那么您可以像这样监视 mkdirSync
方法:
jest.spyOn(fs, 'mkdirSync');
但是,我认为您需要采取不同的方法。
您的 createLogDir
函数是一个静态方法 - 这意味着它只能在类上调用,而不能在该类的实例上调用(new Logger()
是Logger
类的一个实例)。因此,为了测试该功能,您需要导出类而不是它的实例,即:
module.exports = Logger;
然后你可以进行以下测试:
const Logger = require('./logger');
const fs = require('fs');
jest.mock('fs') // this auto mocks all methods on fs - so you can treat fs.existsSync and fs.mkdirSync like you would jest.fn()
it('should create a new log directory if one doesn\'t already exist', () => {
// set up existsSync to meet the `if` condition
fs.existsSync.mockReturnValue(false);
// call the function that you want to test
Logger.createLogDir('test-path');
// make your assertion
expect(fs.mkdirSync).toHaveBeenCalled();
});
it('should NOT create a new log directory if one already exists', () => {
// set up existsSync to FAIL the `if` condition
fs.existsSync.mockReturnValue(true);
Logger.createLogDir('test-path');
expect(fs.mkdirSync).not.toHaveBeenCalled();
});
注意:看起来您正在混合使用 CommonJS 和 es6 模块语法(export default
是 es6)——我会尝试坚持其中一个
关于node.js - 用 Jest 模拟 fs 函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50066138/