I want to mock Math.random for certain tests and use its original implementation for other tests. How can I achieve this? I’ve read about using jest.doMock
and jest.dontMock
, but I’ve bumped into a number of issues using them, like:
- I seem to need
require
in order to usedoMock
anddontMock
, but my project only uses ES6 modules for importing modules - Those functions also have issues taking in a global module like
Math
. I get an error when trying to usejest.doMock("Math.random")
, which results inCannot find module 'Math' from 'app.test.js'
I don’t necessarily need to use doMock
and dontMock
for my tests. They just seemed to be the closest thing I could find in the jest documentation to what I want to achieve. But I’m open to alternative solutions.
My function I want to test inside app.js…
export function getRandomId(max) { if (!Number.isInteger(max) || max <= 0) { throw new TypeError("Max is an invalid type"); } return Math.floor(Math.random() * totalNumPeople) + 1; }
Inside app.test.js…
describe("getRandomId", () => { const max = 10; Math.random = jest.fn(); test("Minimum value for an ID is 1", () => { Math.mockImplementationOnce(() => 0); const id = app.getRandomId(max); expect(id).toBeGreaterThanOrEqual(1); }); test("Error thrown for invalid argument", () => { // I want to use the original implementation of Math.random here expect(() => getRandomId("invalid")).toThrow(); }) });
Advertisement
Answer
Try this:
describe("getRandomId", () => { const max = 10; let randomMock; beforeEach(() => { randomMock = jest.spyOn(global.Math, 'random'); }); test("Minimum value for an ID is 1", () => { randomMock.mockReturnValue(0); const id = getRandomId(max); expect(id).toBeGreaterThanOrEqual(1); }); test("Error thrown for invalid argument", () => { // I want to use the original implementation of Math.random here randomMock.mockRestore(); // restores the original (non-mocked) implementation expect(() => getRandomId("invalid")).toThrow(); }) });