阅读(366) (0)

Jest 对象API

2021-08-10 17:52:05 更新

该jest对象自动在每个测试文件的范围内。jest对象中的方法有助于创建模拟并让你控制 Jest 的整体行为。它也可以通过 via 显式导入​import {jest} from '@jest/globals​'。

模拟模块

jest.disableAutomock()

在模块加载器中禁用自动模拟。

有关更多信息,请参阅配置automock部分

调用此方法后,所有require()s 将返回每个模块的真实版本(而不是模拟版本)。

有配置:

  1. {
  2. "automock": true
  3. }

示例:

  1. // utils.js
  2. export default {
  3. authorize: () => {
  4. return 'token';
  5. },
  6. };
  1. // __tests__/disableAutomocking.js
  2. import utils from '../utils';
  3. jest.disableAutomock();
  4. test('original implementation', () => {
  5. // now we have the original implementation,
  6. // even if we set the automocking in a jest configuration
  7. expect(utils.authorize()).toBe('token');
  8. });

当你要模拟的依赖项数量远小于你不模拟的依赖项数量时,这通常很有用。例如,如果你正在为使用大量依赖项的模块编写测试,这些依赖项可以合理地归类为模块的“实现细节”,那么你可能不想模拟它们。

可能被视为“实现细节”的依赖项示例包括从语言内置(例如 ​Array.prototype​ 方法)到高度通用的实用程序方法(例如下划线​/lo-dash​、数组实用程序等)和整个库(如 ​React​)。 ​js​。

返回jest用于链接的对象。

注意:此方法以前称为​autoMockOff.​ 使用时​babel-jest​,对​disableAutomock​的调用会自动提升到代码块的顶部。使用​autoMockOff​,如果你想明确地避免这种行为。

jest.enableAutomock()

在模块加载器中启用自动模拟。

返回jest用于链接的对象。

有关更多信息,请参阅配置automock部分

示例:

  1. // utils.js
  2. export default {
  3. authorize: () => {
  4. return 'token';
  5. },
  6. isAuthorized: secret => secret === 'wizard',
  7. };
  1. // __tests__/enableAutomocking.js
  2. jest.enableAutomock();
  3. import utils from '../utils';
  4. test('original implementation', () => {
  5. // now we have the mocked implementation,
  6. expect(utils.authorize._isMockFunction).toBeTruthy();
  7. expect(utils.isAuthorized._isMockFunction).toBeTruthy();
  8. });

注意:此方法以前称为​autoMockOn​. 使用时​babel-jest​,对 的调用​enableAutomock​会自动提升到代码块的顶部。使用​autoMockOn​,如果你想明确地避免这种行为。

jest.createMockFromModule(moduleName)

在 Is 26.0.0+ 中重命名

同样在别名下: ​.genMockFromModule(moduleName)

给定模块的名称,使用自动模拟系统为你生成模块的模拟版本。

当你想要创建扩展自动模拟行为的手动模拟时,这很有用。

示例:

  1. // utils.js
  2. export default {
  3. authorize: () => {
  4. return 'token';
  5. },
  6. isAuthorized: secret => secret === 'wizard',
  7. };
  1. // __tests__/createMockFromModule.test.js
  2. const utils = jest.createMockFromModule('../utils').default;
  3. utils.isAuthorized = jest.fn(secret => secret === 'not wizard');
  4. test('implementation created by jest.createMockFromModule', () => {
  5. expect(utils.authorize.mock).toBeTruthy();
  6. expect(utils.isAuthorized('not wizard')).toEqual(true);
  7. });

这是​createMockFromModule​模拟以下数据类型的方式:

函数 Function

创建一个新的模拟函数。新函数没有形式参数,调用时将返回​undefined​。此功能也适用于​async​函数。

类 Class

创建一个新类。原始类的接口被保留,所有的类成员函数和属性都将被模拟。

对象 Object

创建一个新的深度克隆对象。对象键被维护并且它们的值被模拟。

数组 Array

创建一个新的空数组,忽略原始数组。

属性 Primitives

创建一个与原始属性具有相同原始值的新属性。

示例:

  1. // example.js
  2. module.exports = {
  3. function: function square(a, b) {
  4. return a * b;
  5. },
  6. asyncFunction: async function asyncSquare(a, b) {
  7. const result = await a * b;
  8. return result;
  9. },
  10. class: new class Bar {
  11. constructor() {
  12. this.array = [1, 2, 3];
  13. }
  14. foo() {}
  15. },
  16. object: {
  17. baz: 'foo',
  18. bar: {
  19. fiz: 1,
  20. buzz: [1, 2, 3],
  21. },
  22. },
  23. array: [1, 2, 3],
  24. number: 123,
  25. string: 'baz',
  26. boolean: true,
  27. symbol: Symbol.for('a.b.c'),
  28. };
  1. // __tests__/example.test.js
  2. const example = jest.createMockFromModule('./example');
  3. test('should run example code', () => {
  4. // creates a new mocked function with no formal arguments.
  5. expect(example.function.name).toEqual('square');
  6. expect(example.function.length).toEqual(0);
  7. // async functions get the same treatment as standard synchronous functions.
  8. expect(example.asyncFunction.name).toEqual('asyncSquare');
  9. expect(example.asyncFunction.length).toEqual(0);
  10. // creates a new class with the same interface, member functions and properties are mocked.
  11. expect(example.class.constructor.name).toEqual('Bar');
  12. expect(example.class.foo.name).toEqual('foo');
  13. expect(example.class.array.length).toEqual(0);
  14. // creates a deeply cloned version of the original object.
  15. expect(example.object).toEqual({
  16. baz: 'foo',
  17. bar: {
  18. fiz: 1,
  19. buzz: [],
  20. },
  21. });
  22. // creates a new empty array, ignoring the original array.
  23. expect(example.array.length).toEqual(0);
  24. // creates a new property with the same primitive value as the original property.
  25. expect(example.number).toEqual(123);
  26. expect(example.string).toEqual('baz');
  27. expect(example.boolean).toEqual(true);
  28. expect(example.symbol).toEqual(Symbol.for('a.b.c'));
  29. });

jest.mock(moduleName, factory, options)

在需要时使用自动模拟版本模拟模块。​factory​并且​options​是可选的。例如:

  1. // banana.js
  2. module.exports = () => 'banana';
  3. // __tests__/test.js
  4. jest.mock('../banana');
  5. const banana = require('../banana'); // banana will be explicitly mocked.
  6. banana(); // will return 'undefined' because the function is auto-mocked.

第二个参数可用于指定正在运行的显式模块工厂,而不是使用 Jest 的自动模拟功能:

  1. jest.mock('../moduleName', () => {
  2. return jest.fn(() => 42);
  3. });
  4. // This runs the function specified as second argument to `jest.mock`.
  5. const moduleName = require('../moduleName');
  6. moduleName(); // Will return '42';

将​factory​参数用于具有默认导出的 ES6 模块时,​__esModule: true​需要指定该属性。该属性一般由 ​Babel/TypeScript​ 生成,但这里需要手动设置。导入默认导出时,是导入​default​从导出对象命名的属性的指令:

  1. import moduleName, {foo} from '../moduleName';
  2. jest.mock('../moduleName', () => {
  3. return {
  4. __esModule: true,
  5. default: jest.fn(() => 42),
  6. foo: jest.fn(() => 43),
  7. };
  8. });
  9. moduleName(); // Will return 42
  10. foo(); // Will return 43

第三个参数可用于创建虚拟模拟——系统中不存在的模块的模拟:

  1. jest.mock(
  2. '../moduleName',
  3. () => {
  4. /*
  5. * Custom implementation of a module that doesn't exist in JS,
  6. * like a generated module or a native module in react-native.
  7. */
  8. },
  9. {virtual: true},
  10. );
警告:在安装文件(由 指定​setupTestFrameworkScriptFile​)中导入模块将阻止对相关模块及其导入的所有模块进行模拟。

被模拟的模块jest.mock仅针对调用jest.mock. 另一个导入模块的文件将获得原始实现,即使它在模拟模块的测试文件之后运行。

返回jest用于链接的对象。

jest.unmock(moduleName)

指示模块系统不应返回指定模块的模拟版本​require()​(例如,它应始终返回真实模块)。

此 API 最常见的用途是指定给定测试打算测试的模块(因此不想自动模拟)。

返回jest用于链接的对象。

jest.doMock(moduleName, factory, options)

使用时​babel-jest​,对 的调用​mock​会自动提升到代码块的顶部。如果你想明确避免这种行为,请使用此方法。

一个有用的例子是当你想在同一个文件中以不同的方式模拟一个模块时:

  1. beforeEach(() => {
  2. jest.resetModules();
  3. });
  4. test('moduleName 1', () => {
  5. jest.doMock('../moduleName', () => {
  6. return jest.fn(() => 1);
  7. });
  8. const moduleName = require('../moduleName');
  9. expect(moduleName()).toEqual(1);
  10. });
  11. test('moduleName 2', () => {
  12. jest.doMock('../moduleName', () => {
  13. return jest.fn(() => 2);
  14. });
  15. const moduleName = require('../moduleName');
  16. expect(moduleName()).toEqual(2);
  17. });

jest.doMock()​与 ES6 导入一起使用需要额外的步骤。如果你不想​require​在测试中使用,请遵循以下步骤:

  • 我们必须指定​__esModule: true属性​(jest.mock()有关更多信息,请参阅API)。
  • 静态 ES6 模块导入被提升到文件的顶部,因此我们必须使用import().
  • 最后,我们需要一个支持动态导入的环境。请参阅使用 Babel进行初始设置。然后将插件babel-plugin-dynamic-import-node或等效插件添加到你的 Babel 配置中以启用 Node.js 中的动态导入。
  1. beforeEach(() => {
  2. jest.resetModules();
  3. });
  4. test('moduleName 1', () => {
  5. jest.doMock('../moduleName', () => {
  6. return {
  7. __esModule: true,
  8. default: 'default1',
  9. foo: 'foo1',
  10. };
  11. });
  12. return import('../moduleName').then(moduleName => {
  13. expect(moduleName.default).toEqual('default1');
  14. expect(moduleName.foo).toEqual('foo1');
  15. });
  16. });
  17. test('moduleName 2', () => {
  18. jest.doMock('../moduleName', () => {
  19. return {
  20. __esModule: true,
  21. default: 'default2',
  22. foo: 'foo2',
  23. };
  24. });
  25. return import('../moduleName').then(moduleName => {
  26. expect(moduleName.default).toEqual('default2');
  27. expect(moduleName.foo).toEqual('foo2');
  28. });
  29. });

返回jest用于链接的对象。

jest.dontMock(moduleName)

使用时​babel-jest​,对 的调用​unmock​会自动提升到代码块的顶部。如果你想明确避免这种行为,请使用此方法。

返回jest用于链接的对象。

jest.setMock(moduleName, moduleExports)

显式提供模块系统应为指定模块返回的模拟对象。

有时,模块系统通常为你提供的自动生成的模拟有时不足以满足你的测试需求。通常在这些情况下,你应该编写一个更适合相关模块的手动模拟。但是,在极少数情况下,即使是手动模拟也不适合你的目的,你需要在测试中自己构建模拟。

在这些罕见的情况下,你可以使用此 API 手动填充模块系统的模拟模块注册表中的插槽。

返回jest用于链接的对象。

注意 建议jest.mock()改用。该jest.mockAPI的第二个参数是一个模块工厂,而不是预期输出模块对象。

jest.requireActual(moduleName)

返回实际模块而不是模拟,绕过对模块是否应接收模拟实现的所有检查。

示例:

  1. jest.mock('../myModule', () => {
  2. // Require the original module to not be mocked...
  3. const originalModule = jest.requireActual('../myModule');
  4. return {
  5. __esModule: true, // Use it when dealing with esModules
  6. ...originalModule,
  7. getRandom: jest.fn().mockReturnValue(10),
  8. };
  9. });
  10. const getRandom = require('../myModule').getRandom;
  11. getRandom(); // Always returns 10

jest.requireMock(moduleName)

返回一个模拟模块而不是实际模块,绕过对模块是否应该正常需要的所有检查。

jest.resetModules()

重置模块注册表 - 所有必需模块的缓存。这对于隔离本地状态可能在测试之间发生冲突的模块很有用。

示例:

  1. const sum1 = require('../sum');
  2. jest.resetModules();
  3. const sum2 = require('../sum');
  4. sum1 === sum2;
  5. // > false (Both sum modules are separate "instances" of the sum module.)

测试中的示例:

  1. beforeEach(() => {
  2. jest.resetModules();
  3. });
  4. test('works', () => {
  5. const sum = require('../sum');
  6. });
  7. test('works too', () => {
  8. const sum = require('../sum');
  9. // sum is a different copy of the sum module from the previous test.
  10. });

返回jest用于链接的对象。

jest.isolateModules(fn)

jest.isolateModules(fn)​比​jest.resetModules()​为回调函数中加载的模块创建沙箱注册表更进一步。这对于隔离每个测试的特定模块非常有用,这样本地模块状态就不会在测试之间发生冲突。

  1. let myModule;
  2. jest.isolateModules(() => {
  3. myModule = require('myModule');
  4. });
  5. const otherCopyOfMyModule = require('myModule');

模拟功能

jest.fn(implementation)

返回一个新的、未使用的模拟函数。可选地采用模拟实现。

  1. const mockFn = jest.fn();
  2. mockFn();
  3. expect(mockFn).toHaveBeenCalled();
  4. // With a mock implementation:
  5. const returnsTrue = jest.fn(() => true);
  6. console.log(returnsTrue()); // true;

jest.isMockFunction(fn)

确定给定的函数是否是模拟函数。

jest.spyOn(object, methodName)

创建一个类似于​jest.fn​但也跟踪对 的调用的模拟函数​object[methodName]​。返回一个 Jest模拟函数

注意:默认情况下,​jest.spyOn​也会调用​spied​方法。这是与大多数其他测试库不同的行为。如果你想覆盖原来的功能,你可以使用​jest.spyOn(object, methodName).mockImplementation(() => customImplementation)​或​object[methodName] = jest.fn(() => customImplementation);

示例:

  1. const video = {
  2. play() {
  3. return true;
  4. },
  5. };
  6. module.exports = video;

示例测试:

  1. const video = require('./video');
  2. test('plays video', () => {
  3. const spy = jest.spyOn(video, 'play');
  4. const isPlaying = video.play();
  5. expect(spy).toHaveBeenCalled();
  6. expect(isPlaying).toBe(true);
  7. spy.mockRestore();
  8. });

jest.spyOn(object, methodName, accessType?)

Jest 22.1.0+ 开始,该​jest.spyOn​方法采用可选的第三个参数​accessType​,可以是​'get​或​'set'​,这在你想分别监视 ​getter ​或 ​setter ​时被证明是有用的。

示例:

  1. const video = {
  2. // it's a getter!
  3. get play() {
  4. return true;
  5. },
  6. };
  7. module.exports = video;
  8. const audio = {
  9. _volume: false,
  10. // it's a setter!
  11. set volume(value) {
  12. this._volume = value;
  13. },
  14. get volume() {
  15. return this._volume;
  16. },
  17. };
  18. module.exports = audio;

示例测试:

  1. const video = require('./video');
  2. test('plays video', () => {
  3. const spy = jest.spyOn(video, 'play', 'get'); // we pass 'get'
  4. const isPlaying = video.play;
  5. expect(spy).toHaveBeenCalled();
  6. expect(isPlaying).toBe(true);
  7. spy.mockRestore();
  8. });
  9. const audio = require('./audio');
  10. test('plays audio', () => {
  11. const spy = jest.spyOn(audio, 'volume', 'set'); // we pass 'set'
  12. audio.volume = 100;
  13. expect(spy).toHaveBeenCalled();
  14. expect(audio.volume).toBe(100);
  15. spy.mockRestore();
  16. });

jest.clearAllMocks()

清除所有模拟的mock.calls和mock.instances属性。相当于调用.mockClear()每个模拟函数。

返回jest用于链接的对象。

jest.resetAllMocks()

重置所有模拟的状态。相当于调用.mockReset()每个模拟函数。

返回jest用于链接的对象。

jest.restoreAllMocks()

将所有模拟恢复到其原始值。相当于调用.mockRestore()每个模拟函数。请注意,jest.restoreAllMocks()只有在使用jest.spyOn;创建模拟时才有效;其他模拟将要求你手动恢复它们。

模拟计时器

jest.useFakeTimers(implementation?: 'modern' | 'legacy')

指示玩笑使用的标准定时器功能假版本(setTimeout,setInterval,clearTimeout,clearInterval,nextTick,setImmediate和clearImmediate)。

如果你'modern'作为参数传递,@sinonjs/fake-timers将用作实现而不是 Jest 自己的假计时器。这也模拟了额外的计时器,如Date. 'modern'将是 Jest 27 中的默认行为。

返回jest用于链接的对象。

jest.useRealTimers()

指示 Jest 使用标准计时器函数的真实版本。

返回jest用于链接的对象。

jest.runAllTicks()

废气的微-task队列(通常在节点经由接口​process.nextTick​)。

调用此 API 时,所有已通过排队的待处理微任务process.nextTick将被执行。此外,如果这些微任务自己调度新的微任务,这些微任务将不断耗尽,直到队列中没有更多的微任务。

jest.runAllTimers()

废气两者宏-task队列(即,所有的任务排队通过setTimeout(),setInterval()和setImmediate())和微-task队列(通常在节点经由接口​process.nextTick​)。

调用此 API 时,将执行所有未决的宏任务和微任务。如果这些任务自己安排了新任务,那么这些任务将不断耗尽,直到队列中没有剩余任务为止。

这对于在测试期间同步执行 setTimeouts 通常很有用,以便同步断言某些仅在执行​setTimeout()​或​setInterval()​回调后才会发生的行为。有关更多信息,请参阅计时器模拟文档。

jest.runAllImmediates()

耗尽排队的所有任务​setImmediate()​。

注意:使用现代伪定时器实现时,此功能不可用

jest.advanceTimersByTime(msToRun)

在 Is 22.0.0+ 中重命名

同样在别名下: .runTimersToTime()

只执行宏任务队列(即所有由​setTimeout()orsetInterval()​和排队的任务​setImmediate()​)。

调用此 API 时,所有计时器都会提前​msToRun​几毫秒。所有已通过​setTimeout()​或排队​setInterval()​并在此时间范围内执行的未决“宏任务”都将被执行。此外,如果这些宏任务调度将在同一时间范围内执行的新宏任务,则这些宏任务将被执行,直到队列中没有更多宏任务剩余,这应该在​msToRun​几毫秒内运行。

jest.runOnlyPendingTimers()

仅执行当前挂起的宏任务(即,仅执行已排队​setTimeout()​或​setInterval()​到此为止的任务)。如果任何当前挂起的宏任务调度新的宏任务,则该调用将不会执行这些新任务。

这对于诸如被测试模块调度 ​asetTimeout()​其回调以​setTimeout()​递归方式调度另一个(意味着调度永不停止)的场景很有用。在这些情况下,能够一次一步向前运行是很有用的。

jest.advanceTimersToNextTimer(steps)

将所有计时器提前所需的毫秒数,以便仅运行下一个超时/间隔。

或者,你可以提供steps,因此它将运行steps下一次超时/间隔的数量。

jest.clearAllTimers()

从计时器系统中删除任何挂起的计时器。

这意味着,如果任何计时器已被调度(但尚未执行),它们将被清除并且将来永远没有机会执行。

jest.getTimerCount()

返回仍要运行的假计时器的数量。

jest.setSystemTime(now?: number | Date)

设置假定时器使用的当前系统时间。模拟用户在程序运行时更改系统时钟。它会影响当前时间,但它本身不会导致例如定时器触发;他们将完全按照没有调用​jest.setSystemTime()​.

注意:此功能仅在使用现代伪计时器实现时可用

jest.getRealSystemTime()

当​mocking​的时候,​Date.now()​也会被​mock​ 。如果你出于某种原因需要访问实时当前时间,你可以调用此函数。

注意:此功能仅在使用现代伪计时器实现时可用

杂项

jest.setTimeout(timeout)

以毫秒为单位设置测试和挂钩之前/之后的默认超时间隔。这仅影响调用此函数的测试文件。

注意:如果不调用此方法,默认超时间隔为 5 秒。

注意:如果你想为所有测试文件设置超时,一个很好的地方是在​setupFilesAfterEnv​.

示例:

  1. jest.setTimeout(1000); // 1 second

jest.retryTimes()

运行失败的测试 n 次,直到它们通过或直到用尽最大重试次数。这只适用于jest-circus

测试中的示例:

  1. jest.retryTimes(3);
  2. test('will fail', () => {
  3. expect(true).toBe(false);
  4. });

返回jest用于链接的对象。