Framework Guides

API Reference

Timer Mocks

The native timer functions (i.e., setTimeout, setInterval, clearTimeout, clearInterval) are less than ideal for a testing environment since they depend on real time to elapse. Jest は タイマー関数を自分で時間経過をコントロールできる関数に置き換えることができます。 グレート・スコット!

Here we enable fake timers by calling jest.useFakeTimers();. This mocks out setTimeout and other timer functions with mock functions. If running multiple tests inside of one file or describe block, jest.useFakeTimers(); can be called before each test manually or with a setup function such as beforeEach. Not doing so will result in the internal usage counter not being reset.

すべてのタイマーを実行する

Another test we might want to write for this module is one that asserts that the callback is called after 1 second. To do this, we're going to use Jest's timer control APIs to fast-forward time right in the middle of the test:

test('calls the callback after 1 second', () => {
const timerGame = require('../timerGame');
const callback = jest.fn();
timerGame(callback);
// At this point in time, the callback should not have been called yet
expect(callback).not.toBeCalled();
// Fast-forward until all timers have been executed
jest.runAllTimers();
// Now our callback should have been called!
expect(callback).toBeCalled();
expect(callback).toHaveBeenCalledTimes(1);
});

待機中のタイマーを実行する

There are also scenarios where you might have a recursive timer -- that is a timer that sets a new timer in its own callback. For these, running all the timers would be an endless loop… so something like jest.runAllTimers() is not desirable. このような場合には jest.runOnlyPendingTimers() が代わりに利用できます。

// __tests__/infiniteTimerGame-test.js'use strict';
jest.useFakeTimers();
describe('infiniteTimerGame', () => {
test('schedules a 10-second timer after 1 second', () => {
const infiniteTimerGame = require('../infiniteTimerGame');
const callback = jest.fn();
infiniteTimerGame(callback);
// At this point in time, there should have been a single call to// setTimeout to schedule the end of the game in 1 second.
expect(setTimeout).toHaveBeenCalledTimes(1);
expect(setTimeout).toHaveBeenLastCalledWith(expect.any(Function), 1000);
// Fast forward and exhaust only currently pending timers// (but not any new timers that get created during that process)
jest.runOnlyPendingTimers();
// At this point, our 1-second timer should have fired it's callback
expect(callback).toBeCalled();
// And it should have created a new timer to start the game over in// 10 seconds
expect(setTimeout).toHaveBeenCalledTimes(2);
expect(setTimeout).toHaveBeenLastCalledWith(expect.any(Function), 10000);
});
});

指定した時間でタイマーを進める

jest 22.0.0 で runTimersToTime から advanceTimersByTime に改名

別の可能性としては jest.advanceTimersByTime(msToRun) を使うことです。 この API が呼び出されると、すべてのタイマーは msToRun ミリ秒で進みます。 All pending "macro-tasks" that have been queued via setTimeout() or setInterval(), and would be executed during this time frame, will be executed. さらに、それらmacro-task自身が新しいmacro-taskを同じ時間枠でスケジュールしている場合は、 msToRun ミリ秒の範囲で実行されるべきmacro-taskがキューから無くなるまで処理されます。

it('calls the callback after 1 second via advanceTimersByTime', () => {
const timerGame = require('../timerGame');
const callback = jest.fn();
timerGame(callback);
// At this point in time, the callback should not have been called yet
expect(callback).not.toBeCalled();
// Fast-forward until all timers have been executed
jest.advanceTimersByTime(1000);
// Now our callback should have been called!
expect(callback).toBeCalled();
expect(callback).toHaveBeenCalledTimes(1);
});

Lastly, it may occasionally be useful in some tests to be able to clear all of the pending timers. For this, we have jest.clearAllTimers().