Blague: meilleure façon de désactiver la console dans les tests unitaires

91

Je me demande s'il existe une meilleure façon de désactiver les erreurs de console dans un test Jest spécifique (c'est-à-dire restaurer la console d'origine avant / après chaque test).

Voici mon approche actuelle:

describe("Some description", () => {
  let consoleSpy;

  beforeEach(() => {
    if (typeof consoleSpy === "function") {
      consoleSpy.mockRestore();
    }
  });

  test("Some test that should not output errors to jest console", () => {
    expect.assertions(2);

    consoleSpy = jest.spyOn(console, "error").mockImplementation();

    // some function that uses console error
    expect(someFunction).toBe("X");
    expect(consoleSpy).toHaveBeenCalled();
  });

  test("Test that has console available", () => {
    // shows up during jest watch test, just as intended
    console.error("test");
  });
});

Existe-t-il une manière plus propre d'accomplir la même chose? Je voudrais éviter spyOn, mais mockRestoresemble seulement travailler avec .

Merci!

Apidcloud
la source

Réponses:

125

Pour un fichier de spécifications particulier, celui d'Andreas est assez bon. La configuration ci-dessous supprimera les console.loginstructions pour toutes les suites de tests,

jest --silent

(ou)

Pour personnaliser, warn, info and debugvous pouvez utiliser la configuration ci-dessous

__tests __ / setup.js ou jest-preload.js configuré danssetupFilesAfterEnv

global.console = {
  log: jest.fn(), // console.log are ignored in tests

  // Keep native behaviour for other methods, use those to print out things in your own tests, not `console.log`
  error: console.error,
  warn: console.warn,
  info: console.info,
  debug: console.debug,
};

jest.config.js

module.exports = {
    verbose: true,
    setupTestFrameworkScriptFile: "<rootDir>/__tests__/setup.js",
};

Jest v24.x Remarque: setupTestFrameworkScriptFile est obsolète au profit de setupFilesAfterEnv.

module.exports = {
    verbose: true,
    setupFilesAfterEnv: ["<rootDir>/__tests__/setup.js"],
};
Raja Jaganathan
la source
2
Salut! setupTestFrameworkScriptFileest obsolète au profit de setupFilesAfterEnv.
elhoucine le
1
La moquerie global.consoleest en effet un moyen simple de procéder et peut être effectuée via n'importe quelle configuration setupFilesAfterEnv . Faites attention de vous moquer de toutes les méthodes natives de l' consoleobjet ou vous risquez de rencontrer d'autres erreurs inattendues.
Vadorequest
49

Comme chaque fichier de test s'exécute dans son propre thread, il n'est pas nécessaire de le restaurer si vous souhaitez le désactiver pour tous les tests dans un fichier. Pour la même raison, vous pouvez aussi simplement écrire

console.log = jest.fn()
expect(console.log).toHaveBeenCalled();
Andreas Köberle
la source
1
Merci pour les informations à ce sujet. Cela a du sens :) Je cherchais un moyen de le faire uniquement à l'intérieur d'un test spécifique sans avoir à le restaurer (je pensais au départ que c'était le comportement par défaut), mais je suppose qu'avant, chacun fait l'affaire.
Apidcloud
46

Si vous voulez le faire juste pour un test spécifique:

beforeEach(() => {
  jest.spyOn(console, 'warn').mockImplementation(() => {});
});
Constantin
la source
1
c'est génial!
sheriff_paul
20

Je trouve que la réponse ci - dessus re: suppression console.logdans toutes les suites de test a jeté des erreurs lors d'autres consoleméthodes (par exemple warn, error) ont été appelés depuis qu'il remplaçait l'ensemble global consoleobjet.

Cette approche quelque peu similaire a fonctionné pour moi avec Jest 22+:

package.json

"jest": {
  "setupFiles": [...],
  "setupTestFrameworkScriptFile": "<rootDir>/jest/setup.js",
  ...
}

plaisanterie / setup.js

jest.spyOn(global.console, 'log').mockImplementation(() => jest.fn());

En utilisant cette méthode, seule console.logest simulée et les autres consoleméthodes ne sont pas affectées.

nickb
la source
6

Pour moi, une manière plus claire / propre (le lecteur a besoin de peu de connaissances de l'API jest pour comprendre ce qui se passe), consiste simplement à faire manuellement ce que fait mockRestore:

// at start of test you want to suppress
const consoleLog = console.log;
console.log = jest.fn();

// at end of test
console.log = consoleLog;
Michael Liquori
la source
1
Vous devez également couvrir console.info, console.error, console.warn, etc.
Michael Oryl
1
@ michael-liquori pourquoi avez-vous besoin de redémarrer le console.log? Je pense qu'après chaque description, les simulations sont effacées
Jhonatan
2
@Jhonatan Je ne pense pas que ce soit clair après chaque description, bien que je ne l'ai pas testé récemment pour en être sûr. Selon les documents jest, il existe une option de configuration clearMockset resetMocks, mais elles sont toutes les deux par défaut false, et aucune de celles-ci ne rétablit réellement l'implémentation initiale même si elle est définie sur true. Et, étant donné qu'il s'agit d'une option de configuration qui pourrait être modifiée à un moment donné, je pense qu'il est préférable de nettoyer manuellement pour s'assurer que vos tests ne poseront pas de problèmes à l'avenir.
Michael Liquori le
-1

Une autre approche consiste à utiliser process.env.NODE_ENV. De cette façon, on peut choisir sélectivement ce qu'il faut afficher (ou non) lors de l'exécution des tests:

if (process.env.NODE_ENV === 'development') {
  console.log('Show output only while in "development" mode');
} else if (process.env.NODE_ENV === 'test') {
  console.log('Show output only while in "test" mode');
}

ou

const logDev = msg => {
  if (process.env.NODE_ENV === 'development') {
    console.log(msg);
  }
}
logDev('Show output only while in "development" mode');

Cela nécessitera que cette configuration soit placée sur package.json:

"jest": {
  "globals": {
    "NODE_ENV": "test"
  }
}

Notez que cette approche n'est pas une solution directe à la question d'origine, mais donne le résultat attendu tant que l'on a la possibilité de l'envelopper console.logavec la condition mentionnée.

Wallace Sidhrée
la source
1
Ce que l'auteur de la question est de savoir comment désactiver console.log lors des tests. Cette solution n'est pas optimale.
Erick
Pour les copieurs: remplacez ===par !==selon vos besoins. J'utilise cette approche depuis des années et cela fonctionne parfaitement, mais je fais des ajustements en fonction de mes besoins.
Wallace Sidhrée
Ne répond pas à la question réelle.
Michael Oryl
C'est une solution hacky et non personnalisable. Et si désactiver uniquement pour un test spécifique et pas pour l'autre?
Jhonatan le