Tout d'abord, je suis nouveau sur es6
Et jest
.
J'ai une classe Logger
pour instancier winston
et je voudrais la tester.
Voici mon code:
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();
Je voudrais tester ma fonction createLogDir()
. J'ai ma tête, je pense que c'est une bonne idée de tester l'état de fs.existsSync. Si fs.existsSync
Renvoie false
, fs.mkdirSync
Doit être appelé. J'essaie donc d'écrire un test 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();
});
});
Cependant, j'ai une erreur:
● 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)
Pouvez-vous m'aider à déboguer et tester ma fonction s'il vous plaît?
Cordialement.
L'erreur est qu'il recherche une méthode appelée fs.mkdirSync
Sur votre objet logger
, qui n'existe pas. Si vous aviez accès au module fs
dans votre test, vous espionneriez la méthode mkdirSync
comme ceci:
jest.spyOn(fs, 'mkdirSync');
Cependant, je pense que vous devez adopter une approche différente.
Votre fonction createLogDir
est une méthode statique - ce qui signifie qu'elle ne peut être appelée que sur la classe, et non sur une instance de cette classe (new Logger()
est une instance de la classe Logger
). Par conséquent, pour tester cette fonction, vous devez exporter la classe et non une instance de celle-ci, à savoir:
module.exports = Logger;
Ensuite, vous pourriez avoir les tests suivants:
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();
});
Remarque: il semble que vous mélangez la syntaxe du module CommonJS et es6 (export default
Est es6) - j'essaierais de m'en tenir à l'un ou à l'autre