I'm trying to test a function that has setTimeout
inside a promise. However it keeps timing out.
This is the function:
export const sleep = async (duration: number): Promise<void> => {
await new Promise<void>((resolve) => {
setTimeout(resolve, duration);
});
if (process.env.NODE_ENV === "test") {
console.log("sleep end");
}
};
And this is my test:
import { sleep } from "../../helpers/utils";
console.log = jest.fn();
jest.useFakeTimers();
test("calls sleep with correct argument and calls console.log", async () => {
const NODE_ENV = "test";
const SLEEP_DURATION = "100";
process.env = { ...process.env, NODE_ENV, SLEEP_DURATION };
const timeoutSpy = jest.spyOn(global, "setTimeout");
await sleep( SLEEP_DURATION);
jest.runAllTimers();
expect(sleep).toHaveBeenCalledWith( SLEEP_DURATION);
expect(timeoutSpy).toHaveBeenCalledWith( SLEEP_DURATION);
expect(console.log).toHaveBeenCalledWith("sleep end");
});
The problem is that when I try to run this the test fails and gives this message:
thrown: "Exceeded timeout of 5000 ms for a test.
Use jest.setTimeout(newTimeout) to increase the timeout value, if this is a long-running test."
I've tried jest.setTimeout(10000)
which just throws an error of Exceeded timeout of 10000ms ...
Any idea as to why this is happening? Or how to fix it?
Thanks!
CodePudding user response:
Here's a solution that gets closer to what you're going for. Importantly, you can't await
the resolution of the promise using fake timers or it'll never resolve. Instead, you can call assign the return value of the sleep
function to a variable, then run the timers, then await the variable.
I also adjusted your expect
statement for the timeout spy since it takes two arguments. Finally, I removed your expectationt that sleep
gets called with the duration because you're literally doing that in the test, so it doesn't seem worthwhile to make that assertion.
console.log = jest.fn();
jest.useFakeTimers();
test("calls sleep with correct argument and calls console.log", async () => {
const NODE_ENV = "test";
const SLEEP_DURATION = "100";
process.env = { ...process.env, NODE_ENV, SLEEP_DURATION };
const timeoutSpy = jest.spyOn(global, "setTimeout");
const sleepFn = sleep( SLEEP_DURATION);
jest.runAllTimers();
// Now that we ran timers we can await the promise resolving
await sleepFn;
// timeout takes two arguments
expect(timeoutSpy).toHaveBeenCalledWith(
expect.any(Function),
SLEEP_DURATION
);
expect(console.log).toHaveBeenCalledWith("sleep end");
});