Jest 对象
本页面由 PageTurner AI 翻译(测试版)。未经项目官方认可。 发现错误? 报告问题 →
jest 对象在每个测试文件中自动处于作用域内。jest 对象的方法可帮助创建模拟(mock)并控制 Jest 的整体行为,也可通过 import {jest} from '@jest/globals' 显式导入。
本页面由 PageTurner AI 翻译(测试版)。未经项目官方认可。 发现错误? 报告问题 →
本页中的 TypeScript 示例仅在显式导入 Jest API 的情况下才能按文档所述正常工作:
import {expect, jest, test} from '@jest/globals';
有关如何设置 Jest 与 TypeScript 配合使用的详细信息,请查阅入门指南。
方法
- 模块模拟
jest.disableAutomock()jest.enableAutomock()jest.createMockFromModule(moduleName)jest.mock(moduleName, factory, options)jest.Mocked<Source>jest.mocked(source, options?)jest.unmock(moduleName)jest.deepUnmock(moduleName)jest.doMock(moduleName, factory, options)jest.dontMock(moduleName)jest.setMock(moduleName, moduleExports)jest.requireActual(moduleName)jest.requireMock(moduleName)jest.onGenerateMock(cb)jest.resetModules()jest.isolateModules(fn)jest.isolateModulesAsync(fn)
- 模拟函数
- 假计时器
jest.useFakeTimers(fakeTimersConfig?)jest.useRealTimers()jest.runAllTicks()jest.runAllTimers()jest.runAllTimersAsync()jest.runAllImmediates()jest.advanceTimersByTime(msToRun)jest.advanceTimersByTimeAsync(msToRun)jest.runOnlyPendingTimers()jest.runOnlyPendingTimersAsync()jest.advanceTimersToNextTimer(steps)jest.advanceTimersToNextTimerAsync(steps)jest.advanceTimersToNextFrame()jest.clearAllTimers()jest.getTimerCount()jest.now()jest.setSystemTime(now?: number | Date)jest.setTimerTickMode(mode)jest.getRealSystemTime()
- 其他功能
模块模拟
jest.disableAutomock()
禁用模块加载器中的自动模拟功能。
此方法生效的前提是已 通过 automock 配置选项启用自动模拟功能。具体配置细节请参阅相关文档。
- JavaScript
- TypeScript
/** @type {import('jest').Config} */
const config = {
automock: true,
};
module.exports = config;
import type {Config} from 'jest';
const config: Config = {
automock: true,
};
export default config;
调用 disableAutomock() 后,所有 require() 将返回模块的真实版本(而非模拟版本)。
export default {
authorize: () => {
return 'token';
},
};
import utils from '../utils';
jest.disableAutomock();
test('original implementation', () => {
// now we have the original implementation,
// even if we set the automocking in a jest configuration
expect(utils.authorize()).toBe('token');
});
此方法适用于需模拟的依赖远少于不需模拟依赖的场景。例如测试某模块时,若其大量依赖属于"实现细节"范畴(如语言内置方法),通常无需模拟这些依赖。
"实现细节"类依赖包括:语言内置对象(如 Array.prototype 方法)、常用工具库(如 underscore, lodash)以及 React.js 等完整库。
返回 jest 对象以支持链式调用。
使用 babel-jest 时,disableAutomock() 调用会自动提升至代码块顶部。如需显式避免此行为,请改用 autoMockOff()。
jest.enableAutomock()
启用模块加载器中的自动模拟功能。
自动模拟功能详情请参阅 automock 配置选项文档。
示例:
export default {
authorize: () => {
return 'token';
},
isAuthorized: secret => secret === 'wizard',
};
jest.enableAutomock();
import utils from '../utils';
test('original implementation', () => {
// now we have the mocked implementation,
expect(utils.authorize._isMockFunction).toBeTruthy();
expect(utils.isAuthorized._isMockFunction).toBeTruthy();
});
返回 jest 对象以支持链式调用。
使用 babel-jest 时,enableAutomock 调用会自动提升至代码块顶部。如需显式避免此行为,请改用 autoMockOn。
jest.createMockFromModule(moduleName)
根据模块名称,通过自动模拟系统生成该模块的模拟版本。
适用于扩展自动模拟行为的手动模拟场景:
- JavaScript
- TypeScript
module.exports = {
authorize: () => {
return 'token';
},
isAuthorized: secret => secret === 'wizard',
};
const utils = jest.createMockFromModule('../utils');
utils.isAuthorized = jest.fn(secret => secret === 'not wizard');
test('implementation created by jest.createMockFromModule', () => {
expect(jest.isMockFunction(utils.authorize)).toBe(true);
expect(utils.isAuthorized('not wizard')).toBe(true);
});
export const utils = {
authorize: () => {
return 'token';
},
isAuthorized: (secret: string) => secret === 'wizard',
};
const {utils} =
jest.createMockFromModule<typeof import('../utils')>('../utils');
utils.isAuthorized = jest.fn((secret: string) => secret === 'not wizard');
test('implementation created by jest.createMockFromModule', () => {
expect(jest.isMockFunction(utils.authorize)).toBe(true);
expect(utils.isAuthorized('not wizard')).toBe(true);
});
createMockFromModule 对各类数据的模拟方式如下:
Function
创建新的模拟函数。该函数无形式参数,调用时返回 undefined,此特性同样适用于 async 函数。
Class
创建新类。保留原始类接口,但所有成员方法和属性均会被模拟。
Object
创建深度克隆的新对象。保留对象键名,但键值会被模拟。
Array
创建新的空数组(忽略原始数组)。
Primitives
创建与原始属性值相同的新属性。
示例:
module.exports = {
function: function square(a, b) {
return a * b;
},
asyncFunction: async function asyncSquare(a, b) {
const result = (await a) * b;
return result;
},
class: new (class Bar {
constructor() {
this.array = [1, 2, 3];
}
foo() {}
})(),
object: {
baz: 'foo',
bar: {
fiz: 1,
buzz: [1, 2, 3],
},
},
array: [1, 2, 3],
number: 123,
string: 'baz',
boolean: true,
symbol: Symbol.for('a.b.c'),
};
const example = jest.createMockFromModule('../example');
test('should run example code', () => {
// creates a new mocked function with no formal arguments.
expect(example.function.name).toBe('square');
expect(example.function).toHaveLength(0);
// async functions get the same treatment as standard synchronous functions.
expect(example.asyncFunction.name).toBe('asyncSquare');
expect(example.asyncFunction).toHaveLength(0);
// creates a new class with the same interface, member functions and properties are mocked.
expect(example.class.constructor.name).toBe('Bar');
expect(example.class.foo.name).toBe('foo');
expect(example.class.array).toHaveLength(0);
// creates a deeply cloned version of the original object.
expect(example.object).toEqual({
baz: 'foo',
bar: {
fiz: 1,
buzz: [],
},
});
// creates a new empty array, ignoring the original array.
expect(example.array).toHaveLength(0);
// creates a new property with the same primitive value as the original property.
expect(example.number).toBe(123);
expect(example.string).toBe('baz');
expect(example.boolean).toBe(true);
expect(example.symbol).toEqual(Symbol.for('a.b.c'));
});
jest.mock(moduleName, factory, options)
当模块被引入时,自动使用模拟版本进行模拟。factory 和 options 为可选参数。例如:
module.exports = () => 'banana';
jest.mock('../banana');
const banana = require('../banana'); // banana will be explicitly mocked.
banana(); // will return 'undefined' because the function is auto-mocked.
第二个参数可用于指定显式的模块工厂函数,替代 Jest 的自动模拟功能:
- JavaScript
- TypeScript
jest.mock('../moduleName', () => {
return jest.fn(() => 42);
});
// This runs the function specified as second argument to `jest.mock`.
const moduleName = require('../moduleName');
moduleName(); // Will return '42';
// The optional type argument provides typings for the module factory
jest.mock<typeof import('../moduleName')>('../moduleName', () => {
return jest.fn(() => 42);
});
// This runs the function specified as second argument to `jest.mock`.
const moduleName = require('../moduleName');
moduleName(); // Will return '42';
当为具有默认导出的 ES6 模块使用 factory 参数时,需要显式设置 __esModule: true 属性。该属性通常由 Babel/TypeScript 自动生成,此处需手动添加。导入默认导出时,此属性指示应从导出对象导入名为 default 的属性:
import moduleName, {foo} from '../moduleName';
jest.mock('../moduleName', () => {
return {
__esModule: true,
default: jest.fn(() => 42),
foo: jest.fn(() => 43),
};
});
moduleName(); // Will return 42
foo(); // Will return 43
第三个参数可用于创建虚拟模拟(virtual mock)——模拟系统中实际不存在的模块:
jest.mock(
'../moduleName',
() => {
/*
* Custom implementation of a module that doesn't exist in JS,
* like a generated module or a native module in react-native.
*/
},
{virtual: true},
);
在配置文件(由 setupFilesAfterEnv 指定)中导入模块,会阻止该模块及其所有依赖模块被模拟。
通过 jest.mock 模拟的模块仅对调用 jest.mock 的文件生效。其他导入该模块的文件即使在被模拟的测试文件之后运行,仍会获取原始实现。
返回 jest 对象以支持链式调用。
使用 TypeScript 编写测试?可通过 jest.Mocked 工具类型或 jest.mocked() 辅助方法获取类型化的模拟模块。
jest.Mocked<Source>
请参阅 Mock Functions 页面的 TypeScript 用法章节。
jest.mocked(source, options?)
请参阅 Mock Functions 页面的 TypeScript 用法章节。
jest.unmock(moduleName)
指示模块系统永远不应从 require() 返回指定模块的模拟版本(即应始终返回真实模块)。
此 API 最常用于指定测试目标模块(即不希望被自动模拟的模块)。
返回 jest 对象以支持链式调用。
jest.deepUnmock(moduleName)
指示模块系统永远不应返回指定模块及其依赖项的模拟版本。
返回 jest 对象以支持链式调用。
jest.doMock(moduleName, factory, options)
使用 babel-jest 时,mock 调用会被自动提升至代码块顶部。若需显式避免此行为,请使用此方法。
典型应用场景是在同一文件内对模块进行差异化模拟:
- JavaScript
- TypeScript
beforeEach(() => {
jest.resetModules();
});
test('moduleName 1', () => {
jest.doMock('../moduleName', () => {
return jest.fn(() => 1);
});
const moduleName = require('../moduleName');
expect(moduleName()).toBe(1);
});
test('moduleName 2', () => {
jest.doMock('../moduleName', () => {
return jest.fn(() => 2);
});
const moduleName = require('../moduleName');
expect(moduleName()).toBe(2);
});
beforeEach(() => {
jest.resetModules();
});
test('moduleName 1', () => {
// The optional type argument provides typings for the module factory
jest.doMock<typeof import('../moduleName')>('../moduleName', () => {
return jest.fn(() => 1);
});
const moduleName = require('../moduleName');
expect(moduleName()).toBe(1);
});
test('moduleName 2', () => {
jest.doMock<typeof import('../moduleName')>('../moduleName', () => {
return jest.fn(() => 2);
});
const moduleName = require('../moduleName');
expect(moduleName()).toBe(2);
});
配合 ES6 导入语法使用 jest.doMock() 需额外步骤。若测试中不希望使用 require,请遵循:
-
必须指定
__esModule: true属性(详见jest.mock()API 说明)。 -
静态 ES6 模块导入会被提升至文件顶部,因此需改用
import()动态导入。 -
最后,需确保环境支持动态导入。初始设置请参阅 使用 Babel。建议在 Babel 配置中添加 babel-plugin-dynamic-import-node 或等效插件以启用 Node 环境动态导入。
beforeEach(() => {
jest.resetModules();
});
test('moduleName 1', () => {
jest.doMock('../moduleName', () => {
return {
__esModule: true,
default: 'default1',
foo: 'foo1',
};
});
return import('../moduleName').then(moduleName => {
expect(moduleName.default).toBe('default1');
expect(moduleName.foo).toBe('foo1');
});
});
test('moduleName 2', () => {
jest.doMock('../moduleName', () => {
return {
__esModule: true,
default: 'default2',
foo: 'foo2',
};
});
return import('../moduleName').then(moduleName => {
expect(moduleName.default).toBe('default2');
expect(moduleName.foo).toBe('foo2');
});
});
返回 jest 对象以支持链式调用。
jest.dontMock(moduleName)
当使用 babel-jest 时,unmock 的调用会自动提升至代码块顶部。若需显式避免此行为,请使用此方法。
返回 jest 对象以支持链式调用。
jest.setMock(moduleName, moduleExports)
显式指定模块系统应为指定模块返回的模拟对象。
偶尔会出现模块系统自动生成的模拟对象无法满足测试需求的情况。通常此时应编写更合适的手 动模拟。但在极少数情况下,即使手动模拟也不适用,需要在测试内部自行构建模拟对象。
这些罕见场景中,可使用此 API 手动填充模块系统的模拟模块注册表。
返回 jest 对象以支持链式调用。
推荐使用 jest.mock() 替代。jest.mock API 的第二个参数是模块工厂函数而非预期的导出模块对象。
jest.requireActual(moduleName)
绕过所有模拟实现检查,直接返回实际模块而非模拟模块。
- JavaScript
- TypeScript
jest.mock('../myModule', () => {
// Require the original module to not be mocked...
const originalModule = jest.requireActual('../myModule');
return {
__esModule: true, // Use it when dealing with esModules
...originalModule,
getRandom: jest.fn(() => 10),
};
});
const getRandom = require('../myModule').getRandom;
getRandom(); // Always returns 10
jest.mock('../myModule', () => {
// Require the original module to not be mocked...
const originalModule =
jest.requireActual<typeof import('../myModule')>('../myModule');
return {
__esModule: true, // Use it when dealing with esModules
...originalModule,
getRandom: jest.fn(() => 10),
};
});
const getRandom = require('../myModule').getRandom;
getRandom(); // Always returns 10
jest.requireMock(moduleName)
绕过所有常规引用检查,直接返回模拟模块而非实际模块。
jest.onGenerateMock(cb)
注册回调函数,当 Jest 为模块生成模拟时触发。此回调允许在模拟对象返回给其他测试前进行修改。
回调参数:
-
modulePath: string- 被模拟模块的绝对路径 -
moduleMock: T- Jest 为模块生成的模拟对象,可在返回前修改或替换
行为特性:
-
若通过连续调用
onGenerateMock注册多个回调,将按添加顺序执行 -
每个回调接收前一个回调的输出作为其
moduleMock,支持对同一模拟进行多层转换
jest.onGenerateMock((modulePath, moduleMock) => {
// Inspect the module name and decide how to transform the mock
if (modulePath.includes('Database')) {
// For demonstration, let's replace a method with our own custom mock
moduleMock.connect = jest.fn().mockImplementation(() => {
console.log('Connected to mock DB');
});
}
// Return the (potentially modified) mock
return moduleMock;
});
// Apply mock for module
jest.mock('./Database');
// Later in your tests
import Database from './Database';
// The `Database` mock now has any transformations applied by our callback
以下情况不会触发 onGenerateMock 回调:
- 位于
__mocks__目录的手动模拟 - 通过
jest.mock('moduleName', () => { ... })显式提供的工厂函数
jest.resetModules()
重置模块注册表(所有已加载模块的缓存)。适用于隔离因本地状态导致测试间冲突的模块。
示例:
const sum1 = require('../sum');
jest.resetModules();
const sum2 = require('../sum');
sum1 === sum2;
// > false (Both sum modules are separate "instances" of the sum module.)
测试示例:
beforeEach(() => {
jest.resetModules();
});
test('works', () => {
const sum = require('../sum');
});
test('works too', () => {
const sum = require('../sum');
// sum is a different copy of the sum module from the previous test.
});
返回 jest 对象以支持链式调用。
jest.isolateModules(fn)
jest.isolateModules(fn) 比 jest.resetModules() 更彻底,为回调函数内加载的模块创建沙盒注册 表。适用于隔离特定模块,避免测试间本地模块状态冲突。
let myModule;
jest.isolateModules(() => {
myModule = require('myModule');
});
const otherCopyOfMyModule = require('myModule');
jest.isolateModulesAsync(fn)
jest.isolateModulesAsync() 是 jest.isolateModules() 的异步版本,调用方需 await isolateModulesAsync 的执行完成。
let myModule;
await jest.isolateModulesAsync(async () => {
myModule = await import('myModule');
// do async stuff here
});
const otherCopyOfMyModule = await import('myModule');
模拟函数
jest.fn(implementation?)
返回全新的模拟函数,可选择接收模拟实现函数。
const mockFn = jest.fn();
mockFn();
expect(mockFn).toHaveBeenCalled();
// With a mock implementation:
const returnsTrue = jest.fn(() => true);
console.log(returnsTrue()); // true;
关于 TypeScript 用法的详细信息,请参阅模拟函数页面。
jest.isMockFunction(fn)
判断给定函数是否为模拟函数。
jest.replaceProperty(object, propertyKey, value)
将 object[propertyKey] 替换为 value。该属性必须已存在于对象上。同一属性可被多次替换。返回 Jest 的被替换属性。
要模拟定义为 getter 或 setter 的属性,请使用 jest.spyOn(object, methodName, accessType)。要模拟函数,请使用 jest.spyOn(object, methodName)。
所有通过 jest.replaceProperty 替换的属性,都可以在 afterEach 方法中调用 jest.restoreAllMocks 恢复原始值。
示例:
const utils = {
isLocalhost() {
return process.env.HOSTNAME === 'localhost';
},
};
module.exports = utils;
测试示例:
const utils = require('./utils');
afterEach(() => {
// restore replaced property
jest.restoreAllMocks();
});
test('isLocalhost returns true when HOSTNAME is localhost', () => {
jest.replaceProperty(process, 'env', {HOSTNAME: 'localhost'});
expect(utils.isLocalhost()).toBe(true);
});
test('isLocalhost returns false when HOSTNAME is not localhost', () => {
jest.replaceProperty(process, 'env', {HOSTNAME: 'not-localhost'});
expect(utils.isLocalhost()).toBe(false);
});
jest.spyOn(object, methodName)
创建类似于 jest.fn 的模拟函数,同时追踪对 object[methodName] 的调用。返回 Jest 的模拟函数。
默认情况下,jest.spyOn 会调用被监听的原始方法。这与大多数测试库的行为不同。如需覆盖原始函数,可使用 jest.spyOn(object, methodName).mockImplementation(() => customImplementation) 或 object[methodName] = jest.fn(() => customImplementation)。
由于 jest.spyOn 是模拟函数,您可以在 afterEach 钩子的回调函数体中调用 jest.restoreAllMocks 来恢复初始状态。
示例:
const video = {
play() {
return true;
},
};
module.exports = video;
测试示例:
const video = require('./video');
afterEach(() => {
// restore the spy created with spyOn
jest.restoreAllMocks();
});
test('plays video', () => {
const spy = jest.spyOn(video, 'play');
const isPlaying = video.play();
expect(spy).toHaveBeenCalled();
expect(isPlaying).toBe(true);
});
监听方法与 using 关键字
如果您的代码库配置了"显式资源管理"转译(例如使用 TypeScript ≥ 5.2 或 @babel/plugin-proposal-explicit-resource-management 插件),可结合 spyOn 与 using 关键字使用:
test('logs a warning', () => {
using spy = jest.spyOn(console, 'warn');
doSomeThingWarnWorthy();
expect(spy).toHaveBeenCalled();
});
该代码语义等同于:
test('logs a warning', () => {
let spy;
try {
spy = jest.spyOn(console, 'warn');
doSomeThingWarnWorthy();
expect(spy).toHaveBeenCalled();
} finally {
spy.mockRestore();
}
});
这样,当退出当前代码块时,监听函数会自动恢复为原始值。
您还可以进一步使用代码块 将模拟限制在测试的特定部分,同时保持代码可读性。
test('testing something', () => {
{
using spy = jest.spyOn(console, 'warn');
setupStepThatWillLogAWarning();
}
// here, console.warn is already restored to the original value
// your test can now continue normally
});
如果收到 Symbol.dispose 不存在的警告,可能需要添加 polyfill,例如:
if (!Symbol.dispose) {
Object.defineProperty(Symbol, 'dispose', {
get() {
return Symbol.for('nodejs.dispose');
},
});
}
jest.spyOn(object, methodName, accessType?)
自 Jest 22.1.0+ 起,jest.spyOn 方法支持可选的第三个参数 accessType(可取值为 'get' 或 'set'),用于分别监听 getter 或 setter 方法。
示例:
const video = {
// it's a getter!
get play() {
return true;
},
};
module.exports = video;
const audio = {
_volume: false,
// it's a setter!
set volume(value) {
this._volume = value;
},
get volume() {
return this._volume;
},
};
module.exports = audio;
测试示例:
const audio = require('./audio');
const video = require('./video');
afterEach(() => {
// restore the spy created with spyOn
jest.restoreAllMocks();
});
test('plays video', () => {
const spy = jest.spyOn(video, 'play', 'get'); // we pass 'get'
const isPlaying = video.play;
expect(spy).toHaveBeenCalled();
expect(isPlaying).toBe(true);
});
test('plays audio', () => {
const spy = jest.spyOn(audio, 'volume', 'set'); // we pass 'set'
audio.volume = 100;
expect(spy).toHaveBeenCalled();
expect(audio.volume).toBe(100);
});
jest.Replaced<Source>
文档请参见模拟函数页面的 TypeScript 用法章节。
jest.Spied<Source>
文档请参见模拟函数页面的 TypeScript 用法章节。
jest.clearAllMocks()
清除所有模拟函数的 mock.calls、mock.instances、mock.contexts 和 mock.results 属性。相当于对每个被模拟函数调用 .mockClear()。
返回 jest 对象以支持链式调用。
jest.resetAllMocks()
重置所有模拟函数的状态。相当于对每个被模拟函数调用 .mockReset()。
返回 jest 对象以支持链式调用。
jest.restoreAllMocks()
将所有模拟函数和被替换属性恢复到原始值。相当于对每个模拟函数调用 .mockRestore(),并对每个被替换属性调用 .restore()。注意:jest.restoreAllMocks() 仅适用于通过 jest.spyOn() 创建的模拟和通过 jest.replaceProperty() 替换的属性;其他模拟需要手动恢复。
假计时器
jest.useFakeTimers(fakeTimersConfig?)
指示 Jest 使用全局日期、性能、时间和计时器 API 的模拟版本。假计时器实现基于 @sinonjs/fake-timers。
假计时器将替换全局的 Date、performance.now()、queueMicrotask()、setImmediate()、clearImmediate()、setInterval()、clearInterval()、setTimeout() 和 clearTimeout(),其实现会从模拟时钟获取时间。
在 Node 环境中,process.hrtime 和 process.nextTick() 也会被替换;在 JSDOM 环境中,requestAnimationFrame()、cancelAnimationFrame()、requestIdleCallback() 和 cancelIdleCallback() 同样会被替换。
配置选项:
type FakeableAPI =
| 'Date'
| 'hrtime'
| 'nextTick'
| 'performance'
| 'queueMicrotask'
| 'requestAnimationFrame'
| 'cancelAnimationFrame'
| 'requestIdleCallback'
| 'cancelIdleCallback'
| 'setImmediate'
| 'clearImmediate'
| 'setInterval'
| 'clearInterval'
| 'setTimeout'
| 'clearTimeout';
type FakeTimersConfig = {
/**
* If set to `true` all timers will be advanced automatically by 20 milliseconds
* every 20 milliseconds. A custom time delta may be provided by passing a number.
* The default is `false`.
*/
advanceTimers?: boolean | number;
/**
* List of names of APIs that should not be faked. The default is `[]`, meaning
* all APIs are faked.
*/
doNotFake?: Array<FakeableAPI>;
/**
* Use the old fake timers implementation instead of one backed by `@sinonjs/fake-timers`.
* The default is `false`.
*/
legacyFakeTimers?: boolean;
/** Sets current system time to be used by fake timers, in milliseconds. The default is `Date.now()`. */
now?: number | Date;
/**
* The maximum number of recursive timers that will be run when calling `jest.runAllTimers()`.
* The default is `100_000` timers.
*/
timerLimit?: number;
};
调用 jest.useFakeTimers() 将使当前文件内所有测试使用假计时器,直到通过 jest.useRealTimers() 恢复原始计时器。
你可以在任意位置调用 jest.useFakeTimers() 或 jest.useRealTimers():顶层作用域、test 代码块内部等。请注意这是全局操作,会影响同一文件中的其他测试。在同一测试文件中再次调用 jest.useFakeTimers() 将重置内部状态(例如计时器计数)并根据提供的选项重新安装假计时器:
test('advance the timers automatically', () => {
jest.useFakeTimers({advanceTimers: true});
// ...
});
test('do not advance the timers and do not fake `performance`', () => {
jest.useFakeTimers({doNotFake: ['performance']});
// ...
});
test('uninstall fake timers for the rest of tests in the file', () => {
jest.useRealTimers();
// ...
});
某些情况下可能需要使用旧版假计时器实现。可通过以下方式启用(不支持额外选项):
jest.useFakeTimers({
legacyFakeTimers: true,
});
旧版假计时器会将 setImmediate()、clearImmediate()、setInterval()、clearInterval()、setTimeout()、clearTimeout() 替换为 Jest 模拟函数。在 Node 环境中 process.nextTick() 会被替换,在 JSDOM 环境中 requestAnimationFrame() 和 cancelAnimationFrame() 同样会被替换。
返回 jest 对象以支持链式调用。
jest.useRealTimers()
指示 Jest 恢复全局日期、性能、时间和计时器 API 的原始实现。例如,可以在 afterEach 钩子中调用 jest.useRealTimers() 以便在每个测试后恢复计时器:
afterEach(() => {
jest.useRealTimers();
});
test('do something with fake timers', () => {
jest.useFakeTimers();
// ...
});
test('do something with real timers', () => {
// ...
});
返回 jest 对象以支持链式调用。
jest.runAllTicks()
清空微任务队列(在 Node 中通常通过 process.nextTick 接口处理)。
当调用此 API 时,所有通过 process.nextTick 排队的待处理微任务(micro-tasks)都将被执行。此外,如果这些微任务自身又调度了新的微任务,这些新任务也将被持续耗尽,直到队列中不再有剩余微任务。
jest.runAllTimers()
耗尽宏任务队列(即由 setTimeout()、setInterval() 和 setImmediate() 排队的任务)和微任务队列(在 Node.js 中通常通过 process.nextTick 调用)。
调用此 API 时,所有待处理的宏任务和微任务都将执行。如果这些任务自身又调度了新任务,这些新任务也将被持续耗尽,直到队列中不再有剩余任务。
这在测试中同步执行 setTimeout 时特别有用,可以同步断言那些仅在 setTimeout() 或 setInterval() 回调执行后才会发生的行为。更多信息请参阅计时器模拟文档。
jest.runAllTimersAsync()
jest.runAllTimers() 的异步等效方法。允许所有已调度的 Promise 回调在运行计时器之前执行。
使用传统模拟计时器实现时此函数不可用。
jest.runAllImmediates()
耗尽所有由 setImmediate() 排队的任务。
此函数仅在旧版模拟计时器实现中可用。
jest.advanceTimersByTime(msToRun)
仅执行宏任务队列(即由 setTimeout()、setInterval() 和 setImmediate() 排队的任务)。
调用此 API 时,所有计时器将推进 msToRun 毫秒。所有通过 setTimeout() 或 setInterval() 排队的待处理"宏任务",只要在该时间范围内应执行的都会被触发。此外,如果这些宏任务又调度了在相同时间范围内应执行的新宏任务,这些任务也将被持续耗尽,直到队列中不再有应在 msToRun 毫秒内执行的宏任务。
jest.advanceTimersByTimeAsync(msToRun)
jest.advanceTimersByTime(msToRun) 的异步等效方法。允许所有已调度的 Promise 回调在推进计时器之前执行。
使用传统模拟计时器实现时此函数不可用。
jest.runOnlyPendingTimers()
仅执行当前待处理的宏任务(即截至目前通过 setTimeout() 或 setInterval() 排队的任务)。如果当前待处理的宏任务又调度了新宏任务,这些新任务在此次调用中不会被执行。
这在某些场景中非常有用,例如当被测试模块调度了一个 setTimeout(),其回调又递归地调度另一个 setTimeout()(意味着调度永不停止)。这类场景中,能够逐步单步推进时间非常实用。
jest.runOnlyPendingTimersAsync()
jest.runOnlyPendingTimers() 的异步等效方法。允许所有已调度的 Promise 回调在运行计时器之前执行。
使用传统模拟计时器实现时此函数不可用。
jest.advanceTimersToNextTimer(steps)
将计时器推进到下一个即将触发的超时/间隔任务所需的时间点。
可选地,您可以提供 steps 参数,表示将运行接下来的 steps 个待触发的超时/间隔任务。
jest.advanceTimersToNextTimerAsync(steps)
jest.advanceTimersToNextTimer(steps) 的异步等效方法。该方法允许在执行计时器前运行所有已安排的 Promise 回调。
使用传统模拟计时器实现时此函数不可用。
jest.advanceTimersToNextFrame()
推进所有计时器所需毫秒数以执行当前通过 requestAnimationFrame 安排的回调。advanceTimersToNextFrame() 是执行使用 requestAnimationFrame 安排代码的有效方式。
使用传统模拟计时器实现时此函数不可用。
jest.clearAllTimers()
从计时器系统中移除所有待处理计时器。
这意味着如果已安排任何计时器(但尚未执行),它们将被清除且永远不会再有机会执行。
jest.getTimerCount()
返回仍需运行的模拟计时器数量。
jest.now()
返回当前时钟的毫秒时间。若使用真实计时器或 Date 被模拟,则等同于 Date.now()。在其他情况(如传统计时器)下,可用于实现 Date.now()、performance.now() 等的自定义模拟。
jest.setSystemTime(now?: number | Date)
设置模拟计时器使用的当前系统时间。模拟程序运行时用户更改系统时钟的场景。它会影响当前时间但不会直接触发计时器;计时器会像未调用 jest.setSystemTime() 时一样精确触发。
使用传统模拟计时器实现时此函数不可用。
jest.setTimerTickMode(mode)
允许配置模拟计时器的时间推进方式。
配置选项:
type TimerTickMode =
| {mode: 'manual'}
| {mode: 'nextAsync'}
| {mode: 'interval'; delta?: number};
-
manual:计时器不会自动推进,需显式手动调用 tick API(如jest.advanceTimersByTime(ms)、jest.runAllTimers()等) -
nextAsync:时钟将持续中断事件循环并运行下一个计时器,直至模式变更 -
interval:等效于设置advanceTimers: true并指定advanceTimeDelta。若未指定 delta 值则默认使用 20
使用传统模拟计时器实现时此函数不可用。
jest.getRealSystemTime()
模拟时间时,Date.now() 也会被模拟。如需访问真实当前时间,可调用此函数。
使用传统模拟计时器实现时此函数不可用。
其他功能
jest.getSeed()
每次 Jest 运行时都会随机生成种子值,可用于伪随机数生成器或其他场景。
使用 --showSeed 标志在测试报告摘要中打印种子值。手动设置种子值请使用 --seed=<num> CLI 参数。
jest.isEnvironmentTornDown()
若测试环境已销毁则返回 true。
jest.retryTimes(numRetries, options?)
对失败测试重试 n 次直至通过或达到最大重试次数。
jest.retryTimes(3);
test('will fail', () => {
expect(true).toBe(false);
});
若启用 logErrorsBeforeRetry 选项,导致测试失败的报错信息将输出至控制台。
jest.retryTimes(3, {logErrorsBeforeRetry: true});
test('will fail', () => {
expect(true).toBe(false);
});
waitBeforeRetry 为重试前的等待毫秒数。
jest.retryTimes(3, {waitBeforeRetry: 1000});
test('will fail', () => {
expect(true).toBe(false);
});
retryImmediately 选项用于在测试失败后立即重试。若未指定此选项,则会在 Jest 完成运行文件中所有其他测试后再重试。
jest.retryTimes(3, {retryImmediately: true});
test('will fail', () => {
expect(true).toBe(false);
});
返回 jest 对象以支持链式调用。
jest.retryTimes() 必须在测试文件顶层或 describe 块中声明。
此函数仅在默认的 jest-circus 运行器中可用。
jest.setTimeout(timeout)
设置测试文件中所有测试用例及 before/after 钩子的默认超时间隔(单位:毫秒)。此设置仅对调用该函数的测试文件生效。若不调用此方法,默认超时间隔为 5 秒。
示例:
jest.setTimeout(1000); // 1 second
若需为同一文件中的不同测试设置超时间隔,请使用单个测试的 timeout 选项。
如需为所有测试文件设置超时,请使用 testTimeout 配置选项。