//app.js (This is a target of testing.) const moduleA = require("./moduleA.js")(); module.exports = (()=>{ console.log(moduleA.showValue()); moduleA.add(10); console.log(moduleA.showValue()); })();
//moduleA.js (External library like a web API and database module) const moduleA = require("./moduleA.js")(); module.exports = (()=>{ console.log(moduleA.showValue()); moduleA.add(10); console.log(moduleA.showValue()); })();
//app.test.js (BAD CASE) const moduleA = require('../moduleA.js')(); jest.mock('../moduleA.js', () => () => { return { add: jest.fn(), showValue: jest.fn().mockImplementation(() => 1000) }; }); describe("app", () => { test("", () => { require("../app.js"); expect(moduleA.add).toHaveBeenCalled(); //----->Failed. jest says add has never been called. expect(moduleA.showValue).toHaveBeenCalled(); }); });
//app.test.js (GOOD CASE) const moduleA = require('../moduleA.js')(); jest.mock('../moduleA.js', () => () => { this.instance = this.instance || {//---> This mock should be singleton. add: jest.fn(), showValue: jest.fn().mockImplementation(() => 1000) }; return this.instance; }); describe("app", () => { test("", () => { require("../app.js"); expect(moduleA.add).toHaveBeenCalled(); //-----> Pass! expect(moduleA.showValue).toHaveBeenCalled();//-----> Pass! }); });
Here is all source code.
github.com