8

There is a mock I use in many places, so I want to move it into a separate file that can be reused.

I think Jest calls this a "manual mock". However I don't want to use the __mocks__ convention.

The top of the file being tested:

import * as dotenvSafe from "dotenv-safe";

The manual mock file:

const dotenvSafe: any = jest.genMockFromModule("dotenv-safe");

dotenvSafe.load = jest.fn(() => {     // the function I want to mock
  return {
    error: undefined,
    parsed: [],
  };
});

export default dotenvSafe;

At the top of the test file, I tried various things:

  1. jest.setMock("dotenv-safe", "../../mocks/dotenv-safe");
    Doesn't work. The code being tested gets "../../mocks/dotenv-safe.mock" instead of a module.

  2. jest.mock("dotenv-safe", () => require("../../mocks/dotenv-safe"));
    Doesn't work - The code being tested throws TypeError: dotenvSafe.load is not a function.

  3. jest.mock("dotenv-safe", () => { return { load: jest.fn(() => ({error: undefined, parsed: []})) }; });
    Does work! But the mock is inline, and I want to move it to a separate file. I don't want to repeat this in every file.

What is the correct syntax?

lonix
  • 14,255
  • 23
  • 85
  • 176

1 Answers1

6

require("../../mocks/dotenv-safe") equals to module exports. It's default export that is used, so it should be:

jest.mock("dotenv-safe", () => require("../../mocks/dotenv-safe").default);
Estus Flask
  • 206,104
  • 70
  • 425
  • 565
  • Wow! That one word made all the difference, and I spent hours on this trying every combination I found in the docs. – lonix Feb 01 '19 at 08:42
  • estus strikes again! They should call you "jestus" :) – lonix Feb 01 '19 at 08:42
  • There is also another way `jest.setMock("dotenv-safe", require("../../mocks/dotenv-safe"));` – lonix Feb 01 '19 at 09:29
  • @lonix Does it work? I'd expect the same thing with `default` to be applicable here, too. – Estus Flask Feb 01 '19 at 10:03
  • 1
    Yes sorry the `default` is required - I changed my manual mock to `module.exports` format because it is less "surprising" in the consuming code (no need for `default`). My point was that there are two nice ways to do it, `jest.mock` and `jest.setMock`. – lonix Feb 01 '19 at 10:39