web-dev-qa-db-fra.com

Fonction fausse maquette avec plaisanterie

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.

7
Oyabi

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

16
Billy Reilly