javascript - Hvorfor fungerer ikke Jest.useFakeTimers i beforeAll-blokker?


Jeg ønsket å mocke timeout-funksjoner globalt, så jeg la til et kall til jest.useFakeTimers i en beforeAll-blokk. Da jeg kjørte testene mine, kjørte ikke jest.advanceTimersByTime den planlagte koden. Jeg brukte spioner for å bekrefte at mocken faktisk ble kalt. Jeg la imidlertid merke til at hvis jeg flyttet jest.advanceTimersByTime-kallet inn i testfunksjonen, eller inn i en beforeEach-blokk, så fungerte det.

Her er et enkelt eksempel som gjenskaper problemet.

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);
    })

})

Jeg så ingenting i dokumentasjonen som forklarer dette. Jeg bruker Jest 26.6.2.

Svar #1

Det ser ut til at jest.useFakeTimers i dokumentasjonen erstatter setTimeout i produktkode, ikke i testkoden.

Svar #2

Kanskje du kan sjekke jest-oppsettfilen din (som setupFilesAfterEnv-konfigurasjonen). Si, hvis jeg legger de kodene i oppsettfilen, vil det da støte på problemet du nevnte ovenfor:

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

Fordi som standardoppførsel blir callbacken til beforeEach alltid utført etter beforeAll, selv om den er definert før beforeAll.