开玩笑模拟fs功能 [英] Mock fs function with jest
问题描述
首先,我是es6
和jest
的新手.
我有一个用于实例化winston
的Logger
类,我想对其进行测试.
I have a Logger
class for instantiate winston
and I would like to test it.
这是我的代码:
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
测试:
I would like to test my function createLogDir()
.
I my head, I think it's a good idea to test the state of fs.existsSync.
If fs.existsSync
return false
, fs.mkdirSync
must be called.
So I try to write some jest
test :
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();
});
});
但是,我遇到了一个错误:
However, I've got an error :
● 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)
可以帮我调试和测试我的功能吗?
Can you help me to debug and test my function please ?
致谢.
推荐答案
存在错误是因为它正在您的logger
对象上寻找一个名为fs.mkdirSync
的方法,该方法不存在.如果您可以在测试中访问fs
模块,则可以像这样监视mkdirSync
方法:
The error there is because it is looking for a method called fs.mkdirSync
on your logger
object, which doesn't exist. If you had access to the fs
module in your test then you would spy on the mkdirSync
method like this:
jest.spyOn(fs, 'mkdirSync');
但是,我认为您需要采取其他方法.
However, I think you need to take a different approach.
您的createLogDir
函数是静态方法-意味着只能在该类上调用该函数,而不能在该类的实例上调用(new Logger()
是该类Logger
的实例).因此,为了测试该功能,您需要导出该类而不是其实例,即:
Your createLogDir
function is a static method - meaning that it can only be called on the class, and not on an instance of that class (new Logger()
is an instance of the class Logger
). Therefore, in order to test that function you need to export the class and not an instance of it, i.e.:
module.exports = Logger;
然后您可以进行以下测试:
Then you could have the following tests:
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)-我会尝试坚持使用另一种方法
Note: it looks like you're mixing CommonJS and es6 module syntax (export default
is es6) - I would try to stick to one or the other
这篇关于开玩笑模拟fs功能的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!