2
votes

Réinitialiser le module de nœud dans Jest

J'ai une application Node.js où index.js a différentes exportations pour les plates-formes de type Unix et Windows.

import os from "os";

jest.mock("os");

describe("Linux platform", () => {
  test("has `foo` and `bar` methods on Linux platform", () => {
    os.platform.mockImplementation(() => "linux");

    const app = require("../src");
    expect(app.foo).toBeTruthy();
    expect(app.bar).toBeTruthy();
  });
});

describe("Windows platform", () => {
  test("has `foo` and `bar` methods on Windows platform", () => {
    os.platform.mockImplementation(() => "win32");

    const app = require("../src");
    expect(app.foo).toBeTruthy();
    expect(app.bar).toBeTruthy();
  });
});

Et j'essaie de couvrir cela fichier avec des tests unitaires qui ressemble à ceci:

import os from "os";

function throwNotSupportedError() {
  throw new Error("Platform not supported.");
}

console.log(os.platform());

switch (os.platform()) {
  case "darwin":
  case "linux":
    module.exports = {
      foo: require("./unix/foo"),
      bar: require("./unix/bar")
    };
    break;
  case "win32":
    module.exports = {
      foo: require("./win32/foo"),
      bar: require("./win32/bar")
    };
    break;
  default:
    throwNotSupportedError();
}

Le fait est que os.platform.mockImplementation (() => "win32"); fonctionne mais console.log (os.platform ()); affiche toujours linux même si j'importe l'application dans chaque cas de test const app = require (". ./src");.

Où est mon erreur et comment la résoudre?


0 commentaires

3 Réponses :


0
votes

Vous vous moquez du module os dans le cadre de votre test, mais votre code actuel utilise le module dans sa propre portée. jest.mock ne prend que les méthodes exportées et les remplace par jest.fn , donc, en théorie, votre code doit exporter os , puis votre code de test doit simplement exiger votre code une fois en haut du fichier. Votre code de test ne doit pas importer directement os .

Il ne s’agit là que d’une théorie non testée, au fait, en lisant un tutoriel sur Jest se moque .


0 commentaires

0
votes

Vous devrez utiliser jest.resetModules () code> après chaque test pour vider le cache du module:

describe("Windows platform", () => {
    afterEach(() => {
        jest.resetModules();
    })

    //...
})


0 commentaires

2
votes

Réponse de Khang concernant jest.resetModules () indique la bonne direction. Je voudrais ajouter que lorsque vous réinitialisez des modules, les références à toutes les importations passées seront "ignorées" (une nouvelle instance est créée après la réinitialisation). En d'autres termes, import os from "os"; en haut de votre test ne sera plus utilisé après la réinitialisation du module.

Solution

En plus de jest.resetModules () vous devez réimporter (ou dans ce cas requérir) le module os dans le test que vous êtes sur le point d'exécuter. Ce faisant, os.platform.mockImplementation (() => "win32"); sera appliqué à la dernière instance de la maquette du module. Vos deux tests doivent être structurés de cette façon;

jest.mock("os");

describe('Platform specific module', () => {
  beforeEach(() => {
    jest.resetModules();
  });

  describe("Linux platform", () => {
    test("has `foo` and `bar` methods on Linux platform", () => {
      const os = require('os');
      os.platform.mockImplementation(() => "linux");
      ...

Vous pouvez utiliser beforeEach au lieu de afterEach , pour assurez-vous que le module os est propre avant le test. Jest devrait isoler chaque fichier de test, mais mieux vaut prévenir que guérir? Enfin, vous voudriez que beforeEach s'exécute avant tous les tests, pas seulement à l'intérieur de la description de la "plate-forme Windows". Pour ce faire, vous pouvez soit le déplacer à la racine du fichier, soit envelopper les deux describe dans un describe supplémentaire, par exemple

test("has `foo` and `bar` methods on Windows platform", () => {
  const os = require('os');
  os.platform.mockImplementation(() => "win32");

  const app = require("./os-test");
  expect(app.foo).toBeTruthy();
  expect(app.bar).toBeTruthy();
});


0 commentaires