Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Passing expression to Jest.unmock

I am implementing a utility function that will ease calling jest.unmock multiple times

it turns out jest.unmock only expects string literal


jest.unmock('got')   // works

const mod = 'got'
jest.unmock(mod)   // does not work

I tried using eval like the following But it doesn't work

const mod = "'got'"
eval(`jest.unmock(${mod})`)

Is there any work round to do this?

What is the rationale behind this?

like image 473
Mehari Mamo Avatar asked Oct 27 '22 06:10

Mehari Mamo


1 Answers

Jest unmock calls are expected to happen before any import statements, so

jest.unmock("got");
let got = require("got");

works, while

let got = require("got");
jest.unmock("got");

does not.

In order to make this easier to use, Jest provides a babel plugin babel-plugin-jest-hoist that hoists unmock calls to be above all import statements. It makes this code:

let got = require("got");
jest.unmock("got");

get transformed at compile time into

jest.unmock("got");
let got = require("got");

so that even though it looks like you call unmock after import, you are actually calling it before import statements. Playground

If jest-hoist allowed hoisting unmock calls with variables as arguments, there would be errors with variables being used before they are defined:

let got = require("got");
const mod = 'got'
jest.unmock(mod) 

would be transformed into

jest.unmock(mod) 
let got = require("got");
const mod = 'got'

To prevent this, jest-hoist disables hoisting when using variables in arguments. However, without jest.unmock being called before require, the require executes normally with the module still mocked.

To fix this, you can make sure your unmock calls are before any require statements you need to unmock. If your code is:

const mod = 'got'
jest.unmock(mod) 

let got = require("got");

jest-hoist will do nothing and your code will work as expected.

like image 67
pfg Avatar answered Nov 08 '22 14:11

pfg