Spec-Zone.ru › Jest

Объект Jest

Объект jest автоматически доступен в области видимости каждого файла тестов. Методы объекта jest помогают создавать моки и управлять общим поведением Jest. Его также можно импортировать явно с помощью import {jest} from '@jest/globals'.

информация

Примеры TypeScript с этой страницы будут работать, как описано, только если вы явно импортируете API Jest:

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.fn(implementation?)
    • jest.isMockFunction(fn)
    • jest.replaceProperty(object, propertyKey, value)
    • jest.spyOn(object, methodName)
    • jest.spyOn(object, methodName, accessType?)
    • jest.Replaced<Source>
    • jest.Spied<Source>
    • jest.clearAllMocks()
    • jest.resetAllMocks()
    • jest.restoreAllMocks()
  • Поддельные таймеры
    • 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 | Temporal.Instant | Temporal.ZonedDateTime)
    • jest.setTimerTickMode(mode)
    • jest.getRealSystemTime()
  • Прочее
    • jest.getSeed()
    • jest.isEnvironmentTornDown()
    • jest.retryTimes(numRetries, options?)
    • jest.setTimeout(timeout)

Моки модулей

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';
  },
};
utils.js
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');
});
__tests__/disableAutomocking.js

Обычно это полезно, когда количество зависимостей, которые вы хотите замокировать, намного меньше количества зависимостей, которые вы не хотите замокировать. Например, если вы пишете тест для модуля, использующего большое количество зависимостей, которые можно обоснованно отнести к «деталям реализации» модуля, вероятно, вы не захотите создавать для них моки.

К зависимостям, которые можно считать «деталями реализации», относятся самые разные вещи: от встроенных в язык (например, методы Array.prototype) до широко используемых вспомогательных методов (например, underscore, lodash, вспомогательные методы для массивов и т. д.) и целых библиотек, таких как React.js.

Возвращает объект jest для объединения вызовов в цепочку.

совет

При использовании babel-jest вызовы disableAutomock() автоматически переносятся в начало блока кода. Используйте autoMockOff(), если хотите явно избежать такого поведения.

jest.enableAutomock()

Включает автоматическое создание моков в загрузчике модулей.

информация

Дополнительные сведения об автоматическом создании моков см. в документации к параметру конфигурации automock.

Пример:

export default {
  authorize: () => {
    return 'token';
  },
  isAuthorized: secret => secret === 'wizard',
};
utils.js
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();
});
__tests__/enableAutomocking.js

Возвращает объект jest для объединения вызовов в цепочку.

совет

При использовании babel-jest вызовы enableAutomock автоматически переносятся в начало блока кода. Используйте autoMockOn, если хотите явно избежать такого поведения.

jest.createMockFromModule(moduleName)

Укажите имя модуля, и система автоматического создания моков создаст для вас мокированную версию этого модуля.

Это полезно, когда вы хотите создать ручной мок, расширяющий поведение автоматически созданного мока:

  • JavaScript
  • TypeScript
module.exports = {
  authorize: () => {
    return 'token';
  },
  isAuthorized: secret => secret === 'wizard',
};
utils.js
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);
});
__tests__/createMockFromModule.test.js
export const utils = {
  authorize: () => {
    return 'token';
  },
  isAuthorized: (secret: string) => secret === 'wizard',
};
utils.ts
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);
});
__tests__/createMockFromModule.test.ts

Так 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'),
};
example.js
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'));
});
__tests__/example.test.js

jest.mock(moduleName, factory, options)

При подключении модуля создаёт для него мок на основе автоматически созданной версии. Параметры factory и options необязательны. Например:

module.exports = () => 'banana';
banana.js
jest.mock('../banana');

const banana = require('../banana'); // banana will be explicitly mocked.

banana(); // will return 'undefined' because the function is auto-mocked.
__tests__/test.js

Второй аргумент можно использовать, чтобы указать фабрику модуля, которая будет запущена вместо использования функции автоматического создания моков 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';

При использовании параметра factory для модуля ES6 с экспортом по умолчанию необходимо указать свойство __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

Третий аргумент можно использовать для создания виртуальных моков — моков модулей, которых нет в системе:

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>

Документацию см. в разделе Использование TypeScript на странице «Функции-моки».

jest.mocked(source, options?)

Документацию см. в разделе Использование 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);
});

Для использования jest.doMock() с импортами ES6 требуются дополнительные действия. Выполните их, если не хотите использовать require в своих тестах:

  • Нужно указать свойство __esModule: true (подробности см. в описании API jest.mock()).
  • Статические импорты модулей 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(). Второй аргумент API jest.mock — это фабрика модуля, а не ожидаемый объект экспортируемого модуля.

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 мока для модуля. С помощью этой функции можно изменить мок до того, как он будет возвращён остальной части теста.

Параметры функции обратного вызова:

  1. modulePath: string — абсолютный путь к модулю, для которого создаётся мок.
  2. 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 replaced property.

примечание

Для создания моков свойств, определённых как геттеры или сеттеры, используйте jest.spyOn(object, methodName, accessType). Для создания моков функций используйте jest.spyOn(object, methodName).

совет

Все свойства, заменённые с помощью jest.replaceProperty, можно восстановить до исходного значения, вызвав jest.restoreAllMocks в методе afterEach.

Пример:

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 mock function.

примечание

По умолчанию jest.spyOn также вызывает отслеживаемый метод. Это отличается от поведения большинства других библиотек для тестирования. Чтобы заменить исходную функцию, используйте jest.spyOn(object, methodName).mockImplementation(() => customImplementation) или object[methodName] = jest.fn(() => customImplementation).

совет

Поскольку jest.spyOn является моком, исходное состояние можно восстановить, вызвав jest.restoreAllMocks в теле функции обратного вызова, переданной хуку afterEach.

Пример:

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 не существует, возможно, потребуется добавить полифил, например, с помощью такого кода:

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'. Это удобно, если нужно отслеживать геттер или сеттер соответственно.

Пример:

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'
  | 'Temporal';

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. Accepts a millisecond
   * timestamp, a `Date`, a `Temporal.Instant`, or a `Temporal.ZonedDateTime`.
   * The default is `Date.now()`.
   */
  now?: number | Date | Temporal.Instant | Temporal.ZonedDateTime;
  /**
   * 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 для даты, производительности, времени и таймеров. Например, вы можете вызвать jest.useRealTimers() внутри хука afterEach, чтобы восстанавливать таймеры после каждого теста:

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. Кроме того, если эти микрозадачи сами ставят в очередь новые микрозадачи, они будут выполняться до тех пор, пока очередь не опустеет.

jest.runAllTimers()

Выполняет все задачи из очереди макрозадач (то есть все задачи, поставленные в очередь с помощью setTimeout(), setInterval() и setImmediate()) и очереди микрозадач (обычно доступ к ней в Node осуществляется через process.nextTick).

При вызове этого API выполняются все ожидающие макрозадачи и микрозадачи. Если эти задачи сами ставят в очередь новые задачи, они будут выполняться до тех пор, пока очередь не опустеет.

Это часто удобно для синхронного выполнения setTimeout во время теста, чтобы синхронно проверить поведение, которое проявилось бы только после выполнения обратных вызовов setTimeout() или setInterval(). Дополнительные сведения см. в документации «Моки таймеров».

jest.runAllTimersAsync()

Асинхронный аналог jest.runAllTimers(). Он позволяет выполнить все запланированные обратные вызовы промисов до запуска таймеров.

информация

Эта функция недоступна при использовании устаревшей реализации поддельных таймеров.

jest.runAllImmediates()

Выполняет все задачи, поставленные в очередь с помощью setImmediate().

информация

Эта функция доступна только при использовании устаревшей реализации поддельных таймеров.

jest.advanceTimersByTime(msToRun)

Выполняет только очередь макрозадач (то есть все задачи, поставленные в очередь с помощью setTimeout() или setInterval() и setImmediate()).

При вызове этого API время на всех таймерах увеличивается на msToRun миллисекунд. Выполняются все ожидающие «макрозадачи», поставленные в очередь с помощью setTimeout() или setInterval() и подлежащие выполнению в течение этого промежутка времени. Кроме того, если эти макрозадачи ставят в очередь новые макрозадачи, которые должны выполниться в том же промежутке времени, они также будут выполнены. Процесс продолжается, пока в очереди не останется макрозадач, которые должны быть выполнены за msToRun миллисекунд.

msToRun также принимает значение Temporal.Duration. Единицы календарного времени (years, months, weeks) не поддерживаются и вызовут ошибку — вместо них используйте единицы времени (days, hours, minutes, seconds, milliseconds).

jest.advanceTimersByTimeAsync(msToRun)

Асинхронный аналог jest.advanceTimersByTime(msToRun). Он позволяет выполнить все запланированные обратные вызовы промисов до запуска таймеров.

информация

Эта функция недоступна при использовании устаревшей реализации поддельных таймеров.

jest.runOnlyPendingTimers()

Выполняет только макрозадачи, ожидающие выполнения в данный момент (то есть только задачи, поставленные в очередь с помощью setTimeout() или setInterval() к этому моменту). Если какая-либо из ожидающих макрозадач поставит в очередь новые макрозадачи, этот вызов их не выполнит.

Это полезно в ситуациях, когда тестируемый модуль планирует setTimeout(), обратный вызов которого рекурсивно планирует ещё один setTimeout() (то есть планирование никогда не прекращается). В таких ситуациях удобно продвигать время вперёд по одному шагу.

jest.runOnlyPendingTimersAsync()

Асинхронный аналог jest.runOnlyPendingTimers(). Он позволяет выполнить все запланированные обратные вызовы промисов до запуска таймеров.

информация

Эта функция недоступна при использовании устаревшей реализации поддельных таймеров.

jest.advanceTimersToNextTimer(steps)

Продвигает время на всех таймерах на необходимое количество миллисекунд, чтобы сработали только следующие таймауты и интервалы.

При желании можно указать steps, чтобы выполнить следующие таймауты и интервалы в количестве steps.

jest.advanceTimersToNextTimerAsync(steps)

Асинхронный аналог jest.advanceTimersToNextTimer(steps). Он позволяет выполнить все запланированные обратные вызовы промисов до запуска таймеров.

информация

Эта функция недоступна при использовании устаревшей реализации поддельных таймеров.

jest.advanceTimersToNextFrame()

Продвигает время на всех таймерах на необходимое количество миллисекунд для выполнения обратных вызовов, запланированных с помощью requestAnimationFrame. advanceTimersToNextFrame() — удобный способ выполнить код, запланированный с помощью requestAnimationFrame.

информация

Эта функция недоступна при использовании устаревшей реализации поддельных таймеров.

jest.clearAllTimers()

Удаляет все ожидающие таймеры из системы таймеров.

Это означает, что все запланированные таймеры, которые ещё не сработали, будут сброшены и больше не смогут сработать.

jest.getTimerCount()

Возвращает количество поддельных таймеров, которые ещё предстоит выполнить.

jest.now()

Возвращает время текущих часов в миллисекундах. Это эквивалентно Date.now(), если используются настоящие таймеры или если замокан Date. В остальных случаях (например, с устаревшими таймерами) это может быть полезно для создания пользовательских моков Date.now(), performance.now() и т. д.

jest.setSystemTime(now?: number | Date | Temporal.Instant | Temporal.ZonedDateTime)

Задаёт текущее системное время, используемое поддельными таймерами. Имитирует изменение пользователем системных часов во время работы программы. Это влияет на текущее время, но само по себе не приводит, например, к срабатыванию таймеров: они сработают точно так же, как сработали бы без вызова jest.setSystemTime().

Если 'Temporal' подменён (см. useFakeTimers), методы Temporal.Now.* (instant(), zonedDateTimeISO(), plainDateTimeISO() и т. д.) используют поддельные часы. Temporal.Now.timeZoneId() не подменяется.

информация

Эта функция недоступна при использовании устаревшей реализации поддельных таймеров.

jest.setTimerTickMode(mode)

Позволяет настроить способ продвижения времени поддельными таймерами.

Параметры конфигурации:

type TimerTickMode =
  {mode: 'manual'} | {mode: 'nextAsync'} | {mode: 'interval'; delta?: number};
  • manual: таймеры не продвигаются без явных ручных вызовов API для продвижения времени (jest.advanceTimersByTime(ms), jest.runAllTimers() и т. д.).
  • nextAsync: часы будут непрерывно прерывать цикл событий, а затем запускать следующий таймер, пока режим не изменится.
  • interval: то же самое, что указать advanceTimers: true с advanceTimeDelta. Если приращение не задано, по умолчанию используется значение 20.
информация

Эта функция недоступна при использовании устаревшей реализации поддельных таймеров.

jest.getRealSystemTime()

При имитации времени также будет замокан Date.now(). Если по какой-либо причине вам понадобится получить настоящее текущее время, вызовите эту функцию.

информация

Эта функция недоступна при использовании устаревшей реализации поддельных таймеров.

Разное

jest.getSeed()

При каждом запуске Jest случайным образом генерируется начальное значение, которое можно использовать в генераторе псевдослучайных чисел или где-либо ещё.

совет

Используйте флаг --showSeed, чтобы вывести начальное значение в сводку отчёта о тестировании. Чтобы задать начальное значение вручную, используйте аргумент CLI --seed=<num>.

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

entireDescribe повторяет все тесты и хуки в блоке describe, где вызван jest.retryTimes(). При вызове на верхнем уровне повторяется корневой блок describe файла тестов. Пока активен повторный запуск describe, повторные запуски отдельных тестов в его поддереве не применяются.

describe('workflow', () => {
  jest.retryTimes(3, {entireDescribe: true});

  beforeAll(() => {
    // Runs again before each retry.
  });

  test('first step', () => {
    // Passing tests run again with the rest of the block.
  });

  test('second step', () => {
    // A failure retries the entire block.
  });

  afterAll(() => {
    // Runs after every attempt.
  });
});

Каждая попытка выполняет хуки beforeAll блока, дочерние тесты и вложенные блоки describe, а также хуки afterAll. Если зарегистрирована подлежащая повторному запуску ошибка теста или хука, успешно пройденные тесты запускаются заново вместе с остальной частью блока. Если entireDescribe не указан или имеет значение false, jest.retryTimes() сохраняет существующее поведение повторного запуска отдельных тестов.

Параметры повторного запуска вложенных блоков describe сочетаются, начиная с самого внутреннего блока. Каждый раз, когда предок начинает новую попытку, лимиты повторных запусков его потомков начинают отсчитываться заново. Поэтому максимальное количество запусков теста при вложенных повторах describe равно произведению значений (numRetries + 1) для каждого настроенного блока. Блок, для которого задано ноль повторов describe, всё равно устанавливает границу повторов и отключает повторы отдельных тестов в своём поддереве.

Хуки afterAll выполняются после каждой попытки, но ошибки из afterAll и ошибки уровня процесса не приводят к повтору describe. Если одна из них возникает во время попытки, дальнейшие попытки не выполняются, даже если другую ошибку можно было бы повторить, и все ошибки остаются в отчёте.

Необработанные отклонения промисов, принадлежащие тесту, beforeAll, beforeEach или afterEach, участвуют в повторах describe. Отклонения без владельца остаются в отчёте, а ошибки afterAll не подлежат повтору.

Если включена рандомизация тестов, каждый блок describe сохраняет порядок, выбранный для первой попытки, во всех последующих попытках.

retryImmediately применяется только к обычным повторам отдельных тестов. При повторе describe текущая попытка всегда выполняется полностью перед началом следующей.

Возвращает объект jest для цепочки вызовов.

внимание

jest.retryTimes() должен быть объявлен на верхнем уровне файла тестов или в блоке describe.

информация

Эта функция доступна только со средством запуска jest-circus, используемым по умолчанию.

jest.setTimeout(timeout)

Задаёт интервал ожидания по умолчанию (в миллисекундах) для всех тестов и хуков до и после тестов в файле тестов. Это влияет только на файл тестов, из которого вызвана функция. Если этот метод не вызван, интервал ожидания по умолчанию составляет 5 секунд.

Пример:

jest.setTimeout(1000); // 1 second
совет

Чтобы задать интервалы ожидания для разных тестов в одном файле, используйте параметр timeout для каждого отдельного теста.

Чтобы задать интервал ожидания для всех файлов тестов, используйте параметр конфигурации testTimeout.

© 2022 Facebook, Inc.
Licensed under the MIT License.
https://jestjs.io/docs/jest-object

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API