4

I had a functioning Jest/Flow setup for my application. We switched to TypeScript, and all of my tests broke. I converted everything over to .ts and .test.ts and fixed all the bugs. For some reason, none of my __mocks__ are used anymore. ( I had to mock some modules that were failing to automock)

For example, the below code used to mock electron any time it was required, and allow the code to invoke mocked dialogs so i could check that error cases reported errors. Since i converted to TypeScript, any time the require ("electron") is hit in a test, it fails saying remote is undefined.

ex) aFile.test.ts

import reportError from "../aFile.ts";
const { dialog } = require ("electron").remote;

describe ("reportError", () =>
{
   test ("creates dialog", () =>
   {
      const title   = "foo";
      const message = "bar";
      reportError (title, message);

      expect (dialog.showErrorBox).toHaveBeenLastCalledWith (title, message);
   });
});

ex) aFile.ts

const { dialog } = require ("electron").remote;
export default function reportError (title: string, message: string)
{
   dialog.showErrorBox (title, message);
}

ex) __mocks__/electron.js (sibling of node_modules)

module.exports = { remote: { dialog: { showErrorBox: jest.fn () } } };

I know for certain the mock isn't being used, because when i add the following to any failing .test.ts file, it starts to pass:

jest.mock ("electron", () => { return { remote: { dialog: { showErrorBox: jest.fn () } } } });

Why isn't TypeScript finding my __mocks__?

6
  • My guess is that the require('electron') is getting obscured from the jest parser and isn't detected when jest hoists the imports. This would likely require a deep dive into jest’s source. Commented May 5, 2017 at 20:35
  • Having the same problem :( Commented Jun 3, 2017 at 9:19
  • I was able to fix this I will post my workaround tomorrow Commented Jun 4, 2017 at 16:49
  • @jonathanconway hopefully the posted answer helps Commented Jun 5, 2017 at 22:31
  • Are you sure you're exporting the module definition for your mock properly? It seems like you're using standard Javascript / CommonJS module.exports notation, and I'm not sure how well that would play with Typescript. Might I suggest rewriting your mock in Typescript and seeing if that works without the setupFiles setting you added? Commented Jun 13, 2017 at 23:23

2 Answers 2

5

I used the following workaround to fix this:

create mocks.js:

jest.mock ("electron", () => 
  {
     return { remote: { dialog: { showErrorBox: jest.fn () } } };
  });

in package.json add this to the jest section (path to where your mocks.js is):

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

This will globally mock electron, and any other module you declare here, similar to having __mocks__ folder. You could probably put each module in its own file and add to setupFiles array.

Sign up to request clarification or add additional context in comments.

Comments

1

TypeScript, mocks and ES modules

I had this problem, and solved it - TypeScript using __mocks__ for node_modules. I'm using ES modules though as it's many years later.

Since the current answer is a workaround, I thought I'd provide my own config as a genuine solution.

The errors I was seeing

TypeError: localforage.getItem is not a function

Basically a bunch of things were undefined.

Working config

I have a node_module in node_modules/localforage I'd like to mock.

Files that use this module import it with

import localforage from "localforage";

So the mock must have a default export.

Other files import it with import * as localforage from "localforage";

So this means I had to make named export (export const someName) as well.

The mock is in __mocks__/localforage.ts

// localforage doesn't work in node, so simulate it
const fakeLocalForageStore: Record<string, any> = {};

// Exported to allow import * as localforage to work
export const getItem = (key) => {
  return fakeLocalForageStore[key] || null;
};

// Exported to allow import * as localforage to work
export const setItem = (key, value) => {
  return (fakeLocalForageStore[key] = value);
};

// Exported to allow import localforage from "localforage"; to work
export default {
  getItem,
  setItem,
};

Tests simply run:

jest.mock("localforage");

And it works.

Tips on debugging:

  • check how your module is being imported. import name from module? import * as name from module? import { name } from module? Your mock must provide the same exports as your original module. This is the part I suspect most people are having trouble with.
  • __mocks__ for node_modules needs to be in a sibling directory.
  • You can log inside the mock to ensure jest is actually loading it
  • Check how the module is used in modules that use it. Do they use the default export? Do they used named exports? Does your mocked module provide these?

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.