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?
3 Réponses :
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 .
Vous devrez utiliser jest.resetModules () code>
après chaque test pour vider le cache du module:
describe("Windows platform", () => { afterEach(() => { jest.resetModules(); }) //... })
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(); });