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
requirein order to usedoMockanddontMock, 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();
})
});