Why doesn't Jest.useFakeTimers work in beforeAll blocks?

Viewed 292

I wanted to mock timeout functions globally so I added a call to jest.useFakeTimers in a beforeAll block. When I ran my tests, jest.advanceTimersByTime didn't execute the scheduled code. I used spies to confirm that the mock was indeed being called. I noticed however, that if I moved the jest.advanceTimersByTime call into the test function, or into a beforeEach block, it worked.

Here's a simple example that reproduces the problem.

describe('test', () => {

    beforeEach(() => {
        // Only beforeEach block works, NOT beforeAll
        jest.useFakeTimers();
    })

    it('setTimeout calls callback', () => {
        const callback = jest.fn();

        setTimeout(() => {
            callback()
        }, 3000);

        expect(callback).not.toHaveBeenCalled();

        jest.advanceTimersByTime(3000);

        expect(callback).toHaveBeenCalledTimes(1);
    })

})

I didn't see anything in the docs that explains this. I'm using Jest 26.6.2.

2 Answers

Maybe you could check your jest setup file(like setupFilesAfterEnv config). Say, If I put those codes in the setup file, then it will run into the problem you said above:

beforeEach(() => {
  // reset to real timers
  jest.useRealTimers();
})

Because as default behavior, beforeEach's callback is always executed after beforeAll's, even if it is defined before beforeAll.

Seems like jest.useFakeTimers in the documentation replaces setTimeout in product code, not within the test code.

Related