jest.mock of ES6 class yields ReferenceError: require is not defined
Asked Answered
S

2

12

I'm trying to create an automatic mock using jest in my ES6 javascript project.

I'm using node v15.0.1, and jest 26.6.0 on ubuntu 18.04.5.

I have a test file containing the following code:

import RenderBuffer from './renderbuffer.js'

jest.mock('./renderbuffer.js');

beforeEach(() => {
    RenderBuffer.mockClear();
});

When I run the test I run into the following issue:

ReferenceError: require is not defined

      4 | 
      5 | beforeEach(() => {
    > 6 |     RenderBuffer.mockClear();
        |       ^
      7 | });
      8 | 

The error is surprising to me as I'm not using a require statement.

My package.json config contains the following:

"type": "module",
    "main": "src/index.js",
    "devDependencies": {
        "jest": "^26.5.3",
        "jest-canvas-mock": "^2.3.0"
    },
    "jest": {
        "setupFiles": ["jest-canvas-mock"]
    },
    "scripts": {
        "test": "node --experimental-vm-modules node_modules/jest/bin/jest.js",
        "test-coverage": "node --experimental-vm-modules node_modules/jest/bin/jest.js --coverage"
    }

Any ideas as to what the root cause of this issue is?

Switchblade answered 28/10, 2020 at 23:14 Comment(4)
Does the RenderBuffer import use require anywhere?Redaredact
Even if you don't use it, Jest does. It was configured the wrong way. Please, provide the configuration.Heterophyllous
@EstusFlask I have added my package.json config. What configuration have I got wrong?Switchblade
Likely this, --experimental-vm-modules. The support of ESM in Jest is experimental. It's expected to be lacking and buggy. This includes module mocking. Don't use it for real work.Heterophyllous
P
10

You have to disable any source code transformations in order to make it working by setting

{
  transform: {}
}

in your Jest configuration file. By default transform option is configured to use babel-jest. Please refer to this Jest documentation section for more details. Also note that you should import jest explicitly:

import { jest } from '@jest/globals';

Unfortunatelly, it can still have some issues running your tests as other commenters already mentioned. Probably, one should follow this issue to keep tracking changes being made in Jest for ESM support.

For example, I was unlucky to mock static module imports at the moment (version 26.6.2):

jest.(do|un)mock

Since ESM has different "stages" when evaluating a module, jest.mock will not work for static imports. It can work for dynamic imports though, so I think we just have to be clear in the docs about what it supports and what it doesn't.

jest.mock calls are hoisted, but that doesn't help in ESM. We might consider transforming import 'thing' to import('thing') which should allow hoisting to work, but then it's async. Using top-level await is probably a necessity for such an approach. I also think it's invasive enough to warrant a separate option. Something to discuss - we don't need to support everything jest.mock can for for an initial release.

Panchito answered 3/11, 2020 at 12:53 Comment(3)
See also this issue related to jest.mock implementation for ESM.Panchito
how are the issues still open? is jest dead? is there an alternative that's still being updated?Tarah
I'm trying to use jest with selenium JS and still no chance to make it work. It does make ANY sense, I'm trying to learn it because in many jobs is requested.Evalynevan
A
1

You also get the error ReferenceError: require is not defined if one of the files you import has the term mock in it, e.g. generate-user-mock.ts. This is a hidden contract entering some sort of special mocking mode.

Renaming the file to e.g. generate-user-data.ts solves the problem.

Arthrospore answered 5/3 at 11:15 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.