Skip to content
Vitest 2
Main Navigation GuíaAPIConfiguraciónModo NavegadorAvanzado
2.1.9
1.6.1
0.34.6

Español

English
简体中文
繁體中文
Français
Русский
Português – Brasil
Deutsch
日本語
한국어
Italiano
Polski
Türkçe
čeština
magyar

Español

English
简体中文
繁體中文
Français
Русский
Português – Brasil
Deutsch
日本語
한국어
Italiano
Polski
Türkçe
čeština
magyar

Apariencia

Sidebar Navigation

Referencia de la API de pruebas

Funciones Mock

Vi

expect

expectTypeOf

assert

assertType

En esta página

Vi ​

Vitest proporciona funciones útiles a través de su helper vi. Puedes acceder a él globalmente (cuando la configuración de globales está habilitada) o importarlo directamente desde vitest:

js
import { vi } from 'vitest';

Módulos Simulados ​

Esta sección describe la API que puedes usar al simular un módulo. Ten en cuenta que Vitest no soporta simular módulos importados con require().

vi.mock ​

  • Tipo: (path: string, factory?: MockOptions | ((importOriginal: () => unknown) => unknown)) => void
  • Tipo: <T>(path: Promise<T>, factory?: MockOptions | ((importOriginal: () => T) => T | Promise<T>)) => void

Sustituye todos los módulos importados desde la ruta proporcionada por otro módulo. Puedes usar alias de Vite configurados dentro de una ruta. La llamada a vi.mock se eleva (hoisted), por lo que no importa dónde la llames. Siempre se ejecuta antes que cualquier importación. Si necesitas hacer referencia a algunas variables fuera de su alcance, puedes definirlas dentro de vi.hoisted y hacer referencia a ellas dentro de vi.mock.

WARNING

vi.mock solo funciona para módulos que fueron importados con la palabra clave import. No funciona con require.

Para elevar vi.mock, Vitest analiza estáticamente tus archivos. Esto significa que no se puede usar vi que no haya sido importado directamente del paquete vitest (por ejemplo, desde algún archivo de utilidad). Usa vi.mock con vi importado de vitest, o habilita la opción de configuración globals.

Vitest no simulará módulos que fueron importados dentro de un archivo setup porque ya están en caché cuando se ejecuta un archivo de prueba. Puedes llamar a vi.resetModules() dentro de vi.hoisted para limpiar la caché de todos los módulos antes de ejecutar un archivo de prueba.

Si la función factory está definida, todas las importaciones devolverán su resultado. Vitest llama a la factory solo una vez y almacena en caché los resultados para todas las importaciones posteriores hasta que se llama a vi.unmock o vi.doUnmock.

A diferencia de jest, la factory puede ser asíncrona. Puedes usar vi.importActual o un helper con la factory pasada como primer argumento, y obtener el módulo original dentro.

Desde Vitest 2.1, también puedes proporcionar un objeto con una propiedad spy en lugar de una función factory. Si spy es true, entonces Vitest auto-simulará el módulo como de costumbre, pero no sobrescribirá la implementación de las exportaciones. Esto es útil si solo quieres verificar que el método exportado fue llamado correctamente por otro método.

ts
import { calculator } from './src/calculator.ts';

vi.mock('./src/calculator.ts', { spy: true });

// llama a la implementación original,
// pero permite verificar el comportamiento más tarde
const result = calculator(1, 2);

expect(result).toBe(3);
expect(calculator).toHaveBeenCalledWith(1, 2);
expect(calculator).toHaveReturned(3);

Vitest también admite una promesa de módulo en lugar de una cadena en los métodos vi.mock y vi.doMock para un mejor soporte de IDE. Cuando se mueve el archivo, la ruta se actualizará, y importOriginal hereda automáticamente el tipo. Usar esta firma también garantizará que el tipo de retorno de la factory sea compatible con el módulo original (manteniendo las exportaciones opcionales).

ts
// @filename: ./path/to/module.js
export declare function total(...numbers: number[]): number;
// @filename: test.js
import { vi } from 'vitest';
// ---cut---
vi.mock(import('./path/to/module.js'), async importOriginal => {
  const mod = await importOriginal(); // el tipo se infiere
  //    ^?
  return {
    ...mod,
    // reemplazar algunas exportaciones
    total: vi.fn(),
  };
});

Internamente, Vitest sigue operando con una cadena y no con un objeto de módulo.

Sin embargo, si estás usando TypeScript con alias paths configurados en tsconfig.json, el compilador no podrá resolver correctamente los tipos de importación. Para que funcione, asegúrate de reemplazar todas las importaciones con alias por sus rutas relativas correspondientes. Por ejemplo, usa import('./path/to/module.js') en lugar de import('@/module').

WARNING

vi.mock se eleva (en otras palabras, se mueve) a la parte superior del archivo. Esto significa que, independientemente de dónde lo escribas (ya sea dentro de beforeEach o test), realmente se ejecutará antes.

Esto también significa que no puedes usar ninguna variable definida fuera de la factory dentro de la factory.

Si necesitas usar variables dentro de la factory, prueba vi.doMock. Funciona de la misma manera pero no se eleva. Ten en cuenta que solo simula las importaciones subsiguientes.

También puedes hacer referencia a variables definidas por el método vi.hoisted si se declaró antes de vi.mock:

ts
import { namedExport } from './path/to/module.js';

const mocks = vi.hoisted(() => {
  return {
    namedExport: vi.fn(),
  };
});

vi.mock('./path/to/module.js', () => {
  return {
    namedExport: mocks.namedExport,
  };
});

vi.mocked(namedExport).mockReturnValue(100);

expect(namedExport()).toBe(100);
expect(namedExport).toBe(mocks.namedExport);

WARNING

Si estás simulando un módulo con una exportación por defecto, deberás proporcionar una clave default dentro del objeto devuelto por la función factory. Esta es una particularidad específica de los módulos ES; por lo tanto, la documentación de jest puede diferir ya que jest utiliza módulos CommonJS. Por ejemplo,

ts
vi.mock('./path/to/module.js', () => {
  return {
    default: { myDefaultKey: vi.fn() },
    namedExport: vi.fn(),
    // etc...
  };
});

Si hay una carpeta __mocks__ junto a un archivo que estás simulando, y la factory no se proporciona, Vitest intentará encontrar un archivo con el mismo nombre en la subcarpeta __mocks__ y usarlo como un módulo real. Si estás simulando una dependencia, Vitest intentará encontrar una carpeta __mocks__ en la raíz del proyecto (por defecto es process.cwd()). Puedes indicarle a Vitest dónde se encuentran las dependencias a través de la opción de configuración deps.moduleDirectories.

Por ejemplo, tienes esta estructura de archivos:

- __mocks__
  - axios.js
- src
  __mocks__
    - increment.js
  - increment.js
- tests
  - increment.test.js

Si llamas a vi.mock en un archivo de prueba sin proporcionar una factory u opciones, buscará un archivo en la carpeta __mocks__ para usarlo como módulo:

ts
// increment.test.js
import { vi } from 'vitest';

// axios es una exportación por defecto de `__mocks__/axios.js`
import axios from 'axios';

// increment es una exportación nombrada de `src/__mocks__/increment.js`
import { increment } from '../increment.js';

vi.mock('axios');
vi.mock('../increment.js');

axios.get(`/apples/${increment(1)}`);

WARNING

Ten en cuenta que si no llamas a vi.mock, los módulos no se simulan automáticamente. Para replicar el comportamiento de simulación automática de Jest, puedes llamar a vi.mock para cada módulo requerido dentro de setupFiles.

Si no hay una carpeta __mocks__ o una factory proporcionada, Vitest importará el módulo original y auto-simulará todas sus exportaciones. Para conocer las reglas aplicadas, consulta algoritmo.

vi.doMock ​

  • Tipo: (path: string, factory?: MockOptions | ((importOriginal: () => unknown) => unknown)) => void
  • Tipo: <T>(path: Promise<T>, factory?: MockOptions | ((importOriginal: () => T) => T | Promise<T>)) => void

Igual que vi.mock, pero no se eleva a la parte superior del archivo, por lo que puedes hacer referencia a variables en el ámbito global del archivo. La siguiente importación dinámica del módulo se simulará.

WARNING

Esto no simulará módulos que fueron importados antes de que se llamara a este método. No olvides que todas las importaciones estáticas en ESM siempre se elevan, por lo que poner esto antes de una importación estática no forzará que se llame antes de la importación:

ts
vi.doMock('./increment.js'); // esto se llamará _después_ de la declaración de importación

import { increment } from './increment.js';
ts
// ./increment.js
export function increment(number) {
  return number + 1;
}
ts
import { beforeEach, test } from 'vitest';
import { increment } from './increment.js';

// el módulo no está simulado, porque vi.doMock aún no se ha llamado
increment(1) === 2;

let mockedIncrement = 100;

beforeEach(() => {
  // puedes acceder a variables dentro de una factory
  vi.doMock('./increment.js', () => ({ increment: () => ++mockedIncrement }));
});

test('importar el siguiente módulo importa el simulado', async () => {
  // la importación original NO FUE SIMULADA, porque vi.doMock se evalúa DESPUÉS de las importaciones
  expect(increment(1)).toBe(2);
  const { increment: mockedIncrement } = await import('./increment.js');
  // la nueva importación dinámica devuelve el módulo simulado
  expect(mockedIncrement(1)).toBe(101);
  expect(mockedIncrement(1)).toBe(102);
  expect(mockedIncrement(1)).toBe(103);
});

vi.mocked ​

  • Tipo: <T>(obj: T, deep?: boolean) => MaybeMockedDeep<T>
  • Tipo: <T>(obj: T, options?: { partial?: boolean; deep?: boolean }) => MaybePartiallyMockedDeep<T>

Ayuda de tipo para TypeScript. Simplemente devuelve el objeto que se pasó.

Cuando partial es true, esperará un Partial<T> como valor de retorno. Por defecto, esto solo hará que TypeScript crea que los valores de primer nivel están simulados. Puedes pasar { deep: true } como segundo argumento para indicarle a TypeScript que todo el objeto está simulado, si realmente lo está.

ts
// example.ts
export function add(x: number, y: number): number {
  return x + y;
}

export function fetchSomething(): Promise<Response> {
  return fetch('https://vitest.dev/');
}
ts
// example.test.ts
import * as example from './example';

vi.mock('./example');

test('1 + 1 es igual a 10', async () => {
  vi.mocked(example.add).mockReturnValue(10);
  expect(example.add(1, 1)).toBe(10);
});

test('simular valor de retorno con tipado solo parcialmente correcto', async () => {
  vi.mocked(example.fetchSomething).mockResolvedValue(new Response('hello'));
  vi.mocked(example.fetchSomething, { partial: true }).mockResolvedValue({
    ok: false,
  });
  // vi.mocked(example.someFn).mockResolvedValue({ ok: false }) // esto es un error de tipo
});

vi.importActual ​

  • Tipo: <T>(path: string) => Promise<T>

Importa un módulo, omitiendo todas las comprobaciones sobre si debe ser simulado. Puede ser útil si quieres simular un módulo parcialmente.

ts
vi.mock('./example.js', async () => {
  const axios = await vi.importActual('./example.js');

  return { ...axios, get: vi.fn() };
});

vi.importMock ​

  • Tipo: <T>(path: string) => Promise<MaybeMockedDeep<T>>

Importa un módulo con todas sus propiedades (incluidas las propiedades anidadas) simuladas. Sigue las mismas reglas que vi.mock. Para conocer las reglas aplicadas, consulta algoritmo.

vi.unmock ​

  • Tipo: (path: string | Promise<Module>) => void

Elimina un módulo del registro de simulaciones. Todas las llamadas para importar devolverán el módulo original, incluso si fue simulado antes. Esta llamada se eleva a la parte superior del archivo, por lo que solo deshará la simulación de módulos que se definieron en setupFiles, por ejemplo.

vi.doUnmock ​

  • Tipo: (path: string | Promise<Module>) => void

Igual que vi.unmock, pero no se eleva a la parte superior del archivo. La siguiente importación del módulo importará el módulo original en lugar del simulado. Esto no deshará la simulación de módulos importados previamente.

ts
// ./increment.js
export function increment(number) {
  return number + 1;
}
ts
import { increment } from './increment.js';

// increment ya está simulado, porque vi.mock se eleva
increment(1) === 100;

// esto se eleva, y la factory se llama antes de la importación en la línea 1
vi.mock('./increment.js', () => ({ increment: () => 100 }));

// todas las llamadas están simuladas, y `increment` siempre devuelve 100
increment(1) === 100;
increment(30) === 100;

// esto no se eleva, por lo que otra importación devolverá el módulo sin simular
vi.doUnmock('./increment.js');

// esto TODAVÍA devuelve 100, porque `vi.doUnmock` no reevalúa un módulo
increment(1) === 100;
increment(30) === 100;

// la siguiente importación no está simulada, ahora `increment` es la función original que devuelve count + 1
const { increment: unmockedIncrement } = await import('./increment.js');

unmockedIncrement(1) === 2;
unmockedIncrement(30) === 31;

vi.resetModules ​

  • Tipo: () => Vitest

Restablece el registro de módulos limpiando la caché de todos los módulos. Esto permite que los módulos se reevalúen al reimportarlos. Las importaciones de nivel superior no se pueden reevaluar. Puede ser útil para aislar módulos donde el estado local entra en conflicto entre pruebas.

ts
import { vi } from 'vitest';

import { data } from './data.js'; // No se reevaluará antes de cada prueba

beforeEach(() => {
  vi.resetModules();
});

test('cambiar estado', async () => {
  const mod = await import('./some/path.js'); // Se reevaluará
  mod.changeLocalState('new value');
  expect(mod.getLocalState()).toBe('new value');
});

test('el módulo tiene estado antiguo', async () => {
  const mod = await import('./some/path.js'); // Se reevaluará
  expect(mod.getLocalState()).toBe('old value');
});

WARNING

No restablece el registro de simulaciones. Para limpiar el registro de simulaciones, usa vi.unmock o vi.doUnmock.

vi.dynamicImportSettled ​

Espera a que se carguen todas las importaciones. Útil si tienes una llamada síncrona que inicia la importación de un módulo que de otra manera no podrías esperar.

ts
import { expect, test } from 'vitest';

// no se puede rastrear la importación porque no se devuelve una Promesa
function renderComponent() {
  import('./component.js').then(({ render }) => {
    render();
  });
}

test('las operaciones se resuelven', async () => {
  renderComponent();
  await vi.dynamicImportSettled();
  expect(document.querySelector('.component')).not.toBeNull();
});

TIP

Si durante una importación dinámica se inicia otra importación dinámica, este método esperará hasta que todas se resuelvan.

Este método también esperará al siguiente tick de setTimeout después de que se resuelva la importación para que todas las operaciones síncronas se completen cuando se resuelva.

Simulación de Funciones y Objetos ​

Esta sección describe cómo trabajar con simulaciones de métodos y reemplazar variables de entorno y globales.

vi.fn ​

  • Tipo: (fn?: Function) => Mock

Crea un espía en una función, aunque se puede iniciar sin una. Cada vez que se invoca una función, almacena sus argumentos de llamada, retornos e instancias. Además, puedes manipular su comportamiento con métodos. Si no se proporciona ninguna función, la simulación devolverá undefined cuando se invoque.

ts
const getApples = vi.fn(() => 0);

getApples();

expect(getApples).toHaveBeenCalled();
expect(getApples).toHaveReturnedWith(0);

getApples.mockReturnValueOnce(5);

const res = getApples();
expect(res).toBe(5);
expect(getApples).toHaveNthReturnedWith(2, 5);

vi.isMockFunction ​

  • Tipo: (fn: Function) => boolean

Comprueba que un parámetro dado es una función simulada. Si estás usando TypeScript, también restringirá su tipo.

vi.clearAllMocks ​

Llamará a .mockClear() en todos los espías. Esto limpiará el historial de simulación, pero no restablecerá su implementación a la predeterminada.

vi.resetAllMocks ​

Llamará a .mockReset() en todos los espías. Esto limpiará el historial de simulación y restablecerá su implementación a una función vacía (devolverá undefined).

vi.restoreAllMocks ​

Llamará a .mockRestore() en todos los espías. Esto limpiará el historial de simulación y restablecerá su implementación a la original.

vi.spyOn ​

  • Tipo: <T, K extends keyof T>(object: T, method: K, accessType?: 'get' | 'set') => MockInstance

Crea un espía en un método o getter/setter de un objeto similar a vi.fn(). Devuelve una función simulada.

ts
let apples = 0;
const cart = {
  getApples: () => 42,
};

const spy = vi.spyOn(cart, 'getApples').mockImplementation(() => apples);
apples = 1;

expect(cart.getApples()).toBe(1);

expect(spy).toHaveBeenCalled();
expect(spy).toHaveReturnedWith(1);

TIP

Puedes llamar a vi.restoreAllMocks dentro de afterEach (o habilitar test.restoreMocks) para restaurar todos los métodos a sus implementaciones originales. Esto restaurará el descriptor de objeto original, por lo que no podrás cambiar la implementación del método:

ts
const cart = {
  getApples: () => 42,
};

const spy = vi.spyOn(cart, 'getApples').mockReturnValue(10);

console.log(cart.getApples()); // 10
vi.restoreAllMocks();
console.log(cart.getApples()); // 42
spy.mockReturnValue(10);
console.log(cart.getApples()); // ¡todavía 42!

TIP

No es posible espiar métodos exportados en Modo Navegador. En su lugar, puedes espiar cada método exportado llamando a vi.mock("./file-path.js", { spy: true }). Esto simulará cada exportación pero mantendrá su implementación intacta, permitiéndote afirmar si el método fue llamado correctamente.

ts
import { calculator } from './src/calculator.ts';

vi.mock('./src/calculator.ts', { spy: true });

calculator(1, 2);

expect(calculator).toHaveBeenCalledWith(1, 2);
expect(calculator).toHaveReturned(3);

Y aunque es posible espiar exportaciones en jsdom u otros entornos Node.js, esto podría cambiar en el futuro.

vi.stubEnv ​

  • Tipo: <T extends string>(name: T, value: T extends "PROD" | "DEV" | "SSR" ? boolean : string | undefined) => Vitest

Cambia el valor de una variable de entorno en process.env e import.meta.env. Puedes restaurar su valor llamando a vi.unstubAllEnvs.

ts
import { vi } from 'vitest';

// `process.env.NODE_ENV` e `import.meta.env.NODE_ENV`
// son "development" antes de llamar a "vi.stubEnv"

vi.stubEnv('NODE_ENV', 'production');

process.env.NODE_ENV === 'production';
import.meta.env.NODE_ENV === 'production';

vi.stubEnv('NODE_ENV', undefined);

process.env.NODE_ENV === undefined;
import.meta.env.NODE_ENV === undefined;

// no cambia otras variables de entorno
import.meta.env.MODE === 'development';

TIP

También puedes cambiar el valor simplemente asignándolo, pero no podrás usar vi.unstubAllEnvs para restaurar el valor anterior:

ts
import.meta.env.MODE = 'test';

vi.unstubAllEnvs ​

  • Tipo: () => Vitest

Restaura todos los valores de import.meta.env y process.env que fueron cambiados con vi.stubEnv. Cuando se llama por primera vez, Vitest recuerda el valor original y lo almacenará hasta que se vuelva a llamar a unstubAllEnvs.

ts
import { vi } from 'vitest';

// `process.env.NODE_ENV` e `import.meta.env.NODE_ENV`
// son "development" antes de llamar a stubEnv

vi.stubEnv('NODE_ENV', 'production');

process.env.NODE_ENV === 'production';
import.meta.env.NODE_ENV === 'production';

vi.stubEnv('NODE_ENV', 'staging');

process.env.NODE_ENV === 'staging';
import.meta.env.NODE_ENV === 'staging';

vi.unstubAllEnvs();

// restaura al valor que se almacenó antes de la primera llamada a "stubEnv"
process.env.NODE_ENV === 'development';
import.meta.env.NODE_ENV === 'development';

vi.stubGlobal ​

  • Tipo: (name: string | number | symbol, value: unknown) => Vitest

Cambia el valor de una variable global. Puedes restaurar su valor original llamando a vi.unstubAllGlobals.

ts
import { vi } from 'vitest';

// `innerWidth` es "0" antes de llamar a stubGlobal

vi.stubGlobal('innerWidth', 100);

innerWidth === 100;
globalThis.innerWidth === 100;
// si estás usando jsdom o happy-dom
window.innerWidth === 100;

TIP

También puedes cambiar el valor simplemente asignándolo a globalThis o window (si estás usando el entorno jsdom o happy-dom), pero no podrás usar vi.unstubAllGlobals para restaurar el valor original:

ts
globalThis.innerWidth = 100;
// si estás usando jsdom o happy-dom
window.innerWidth = 100;

vi.unstubAllGlobals ​

  • Tipo: () => Vitest

Restaura todos los valores globales en globalThis/global (y window/top/self/parent, si estás usando el entorno jsdom o happy-dom) que fueron cambiados con vi.stubGlobal. Cuando se llama por primera vez, Vitest recuerda el valor original y lo almacenará hasta que se vuelva a llamar a unstubAllGlobals.

ts
import { vi } from 'vitest';

const Mock = vi.fn();

// IntersectionObserver es "undefined" antes de llamar a "stubGlobal"

vi.stubGlobal('IntersectionObserver', Mock);

IntersectionObserver === Mock;
global.IntersectionObserver === Mock;
globalThis.IntersectionObserver === Mock;
// si estás usando jsdom o happy-dom
window.IntersectionObserver === Mock;

vi.unstubAllGlobals();

globalThis.IntersectionObserver === undefined;
'IntersectionObserver' in globalThis === false;
// lanza ReferenceError, porque no está definido
IntersectionObserver === undefined;

Temporizadores Falsos ​

Esta sección describe cómo trabajar con temporizadores falsos.

vi.advanceTimersByTime ​

  • Tipo: (ms: number) => Vitest

Este método invocará cada temporizador iniciado hasta que pase el número especificado de milisegundos o la cola esté vacía, lo que ocurra primero.

ts
let i = 0;
setInterval(() => console.log(++i), 50);

vi.advanceTimersByTime(150);

// log: 1
// log: 2
// log: 3

vi.advanceTimersByTimeAsync ​

  • Tipo: (ms: number) => Promise<Vitest>

Este método invocará cada temporizador iniciado hasta que pase el número especificado de milisegundos o la cola esté vacía, lo que ocurra primero. Esto incluirá temporizadores establecidos de forma asíncrona.

ts
let i = 0;
setInterval(() => Promise.resolve().then(() => console.log(++i)), 50);

await vi.advanceTimersByTimeAsync(150);

// log: 1
// log: 2
// log: 3

vi.advanceTimersToNextTimer ​

  • Tipo: () => Vitest

Llamará al siguiente temporizador disponible. Útil para hacer afirmaciones entre cada llamada al temporizador. Puedes encadenar llamadas para gestionar los temporizadores tú mismo.

ts
let i = 0;
setInterval(() => console.log(++i), 50);

vi.advanceTimersToNextTimer() // log: 1
  .advanceTimersToNextTimer() // log: 2
  .advanceTimersToNextTimer(); // log: 3

vi.advanceTimersToNextTimerAsync ​

  • Tipo: () => Promise<Vitest>

Llamará al siguiente temporizador disponible y esperará hasta que se resuelva si se estableció de forma asíncrona. Útil para hacer afirmaciones entre cada llamada al temporizador.

ts
let i = 0;
setInterval(() => Promise.resolve().then(() => console.log(++i)), 50);

await vi.advanceTimersToNextTimerAsync(); // log: 1
expect(console.log).toHaveBeenCalledWith(1);

await vi.advanceTimersToNextTimerAsync(); // log: 2
await vi.advanceTimersToNextTimerAsync(); // log: 3

vi.advanceTimersToNextFrame 2.1.0+ ​

  • Tipo: () => Vitest

Similar a vi.advanceTimersByTime, pero avanzará los temporizadores por los milisegundos necesarios para ejecutar las devoluciones de llamada actualmente programadas con requestAnimationFrame.

ts
let frameRendered = false;

requestAnimationFrame(() => {
  frameRendered = true;
});

vi.advanceTimersToNextFrame();

expect(frameRendered).toBe(true);

vi.getTimerCount ​

  • Tipo: () => number

Obtiene el número de temporizadores en espera.

vi.clearAllTimers ​

Elimina todos los temporizadores que están programados para ejecutarse. Estos temporizadores nunca se ejecutarán en el futuro.

vi.getMockedSystemTime ​

  • Tipo: () => Date | null

Devuelve la fecha actual simulada que se estableció usando setSystemTime. Si la fecha no está simulada, el método devolverá null.

vi.getRealSystemTime ​

  • Tipo: () => number

Cuando se usa vi.useFakeTimers, las llamadas a Date.now se simulan. Si necesitas obtener la hora real en milisegundos, puedes llamar a esta función.

vi.runAllTicks ​

  • Tipo: () => Vitest

Llama a cada microtarea que fue encolada por process.nextTick. Esto también ejecutará todas las microtareas programadas por sí mismas.

vi.runAllTimers ​

  • Tipo: () => Vitest

Este método invocará cada temporizador iniciado hasta que la cola de temporizadores esté vacía. Esto significa que cada temporizador llamado durante runAllTimers se disparará. Si tienes un intervalo infinito, lanzará una excepción después de 10.000 intentos (se puede configurar con fakeTimers.loopLimit).

ts
let i = 0;
setTimeout(() => console.log(++i));
const interval = setInterval(() => {
  console.log(++i);
  if (i === 3) {
    clearInterval(interval);
  }
}, 50);

vi.runAllTimers();

// log: 1
// log: 2
// log: 3

vi.runAllTimersAsync ​

  • Tipo: () => Promise<Vitest>

Este método invocará asíncronamente cada temporizador iniciado hasta que la cola de temporizadores esté vacía. Esto significa que cada temporizador llamado durante runAllTimersAsync se disparará, incluso los temporizadores asíncronos. Si tienes un intervalo infinito, lanzará una excepción después de 10.000 intentos (se puede configurar con fakeTimers.loopLimit).

ts
setTimeout(async () => {
  console.log(await Promise.resolve('result'));
}, 100);

await vi.runAllTimersAsync();

// log: result

vi.runOnlyPendingTimers ​

  • Tipo: () => Vitest

Este método llamará a cada temporizador que se inició después de la llamada a vi.useFakeTimers. No disparará ningún temporizador que se haya iniciado durante su llamada.

ts
let i = 0;
setInterval(() => console.log(++i), 50);

vi.runOnlyPendingTimers();

// log: 1

vi.runOnlyPendingTimersAsync ​

  • Tipo: () => Promise<Vitest>

Este método llamará asíncronamente a cada temporizador que se inició después de la llamada a vi.useFakeTimers, incluso los asíncronos. No disparará ningún temporizador que se haya iniciado durante su llamada.

ts
setTimeout(() => {
  console.log(1);
}, 100);
setTimeout(() => {
  Promise.resolve().then(() => {
    console.log(2);
    setInterval(() => {
      console.log(3);
    }, 40);
  });
}, 10);

await vi.runOnlyPendingTimersAsync();

// log: 2
// log: 3
// log: 3
// log: 1

vi.setSystemTime ​

  • Tipo: (date: string | number | Date) => void

Si los temporizadores falsos están habilitados, este método simula que un usuario cambia el reloj del sistema (afectará a la API relacionada con la fecha como hrtime, performance.now o new Date()) - sin embargo, no disparará ningún temporizador. Si los temporizadores falsos no están habilitados, este método solo simulará las llamadas a Date.*.

Útil si necesitas probar algo que depende de la fecha actual, por ejemplo, llamadas a Luxon dentro de tu código.

Acepta los mismos argumentos de cadena y número que Date.

ts
const date = new Date(1998, 11, 19);

vi.useFakeTimers();
vi.setSystemTime(date);

expect(Date.now()).toBe(date.valueOf());

vi.useRealTimers();

vi.useFakeTimers ​

  • Tipo: (config?: FakeTimerInstallOpts) => Vitest

Para habilitar la simulación de temporizadores, debes llamar a este método. Envolverá todas las llamadas posteriores a temporizadores (como setTimeout, setInterval, clearTimeout, clearInterval, setImmediate, clearImmediate, y Date) hasta que se llame a vi.useRealTimers().

La simulación de nextTick no es compatible cuando se ejecuta Vitest dentro de node:child_process usando --pool=forks. NodeJS usa process.nextTick internamente en node:child_process y se cuelga cuando se simula. La simulación de nextTick es compatible cuando se ejecuta Vitest con --pool=threads.

La implementación se basa internamente en @sinonjs/fake-timers.

TIP

vi.useFakeTimers() no simula automáticamente process.nextTick. Pero puedes habilitarlo especificando la opción en el argumento toFake: vi.useFakeTimers({ toFake: ['nextTick'] }).

vi.isFakeTimers ​

  • Tipo: () => boolean

Devuelve true si los temporizadores falsos están habilitados.

vi.useRealTimers ​

  • Tipo: () => Vitest

Cuando los temporizadores se agotan, puedes llamar a este método para devolver los temporizadores simulados a sus implementaciones originales. Todos los temporizadores que se programaron antes se descartarán.

Miscelánea ​

Un conjunto de funciones de ayuda útiles que Vitest proporciona.

vi.waitFor ​

  • Tipo: <T>(callback: WaitForCallback<T>, options?: number | WaitForOptions) => Promise<T>

Espera a que la devolución de llamada se ejecute correctamente. Si la devolución de llamada lanza un error o devuelve una promesa rechazada, seguirá esperando hasta que tenga éxito o se agote el tiempo de espera.

Esto es muy útil cuando necesitas esperar a que se complete alguna acción asíncrona, por ejemplo, cuando inicias un servidor y necesitas esperar a que se inicie.

ts
import { expect, test, vi } from 'vitest';
import { createServer } from './server.js';

test('Servidor iniciado correctamente', async () => {
  const server = createServer();

  await vi.waitFor(
    () => {
      if (!server.isReady) {
        throw new Error('Servidor no iniciado');
      }

      console.log('Servidor iniciado');
    },
    {
      timeout: 500, // por defecto es 1000
      interval: 20, // por defecto es 50
    }
  );
  expect(server.isReady).toBe(true);
});

También funciona para devoluciones de llamada asíncronas

ts
// @vitest-environment jsdom

import { expect, test, vi } from 'vitest';
import { getDOMElementAsync, populateDOMAsync } from './dom.js';

test('El elemento existe en el DOM', async () => {
  // empezar a poblar el DOM
  populateDOMAsync();

  const element = await vi.waitFor(
    async () => {
      // intentar obtener el elemento hasta que exista
      const element = (await getDOMElementAsync()) as HTMLElement | null;
      expect(element).toBeTruthy();
      expect(element.dataset.initialized).toBeTruthy();
      return element;
    },
    {
      timeout: 500, // por defecto es 1000
      interval: 20, // por defecto es 50
    }
  );
  expect(element).toBeInstanceOf(HTMLElement);
});

Si se usa vi.useFakeTimers, vi.waitFor llama automáticamente a vi.advanceTimersByTime(interval) en cada devolución de llamada de verificación.

vi.waitUntil ​

  • Tipo: <T>(callback: WaitUntilCallback<T>, options?: number | WaitUntilOptions) => Promise<T>

Esto es similar a vi.waitFor, pero si la devolución de llamada lanza algún error, la ejecución se interrumpe inmediatamente y se recibe un mensaje de error. Si la devolución de llamada devuelve un valor falsy, la siguiente verificación continuará hasta que se devuelva un valor truthy. Esto es útil cuando necesitas esperar a que algo exista antes de dar el siguiente paso.

Mira el ejemplo a continuación. Podemos usar vi.waitUntil para esperar a que el elemento aparezca en la página, y luego podemos hacer algo con el elemento.

ts
import { expect, test, vi } from 'vitest';

test('El elemento se renderiza correctamente', async () => {
  const element = await vi.waitUntil(() => document.querySelector('.element'), {
    timeout: 500, // por defecto es 1000
    interval: 20, // por defecto es 50
  });

  // hacer algo con el elemento
  expect(element.querySelector('.element-child')).toBeTruthy();
});

vi.hoisted ​

  • Tipo: <T>(factory: () => T) => T

Todas las declaraciones import estáticas en los módulos ES se elevan a la parte superior del archivo, por lo que cualquier código que se defina antes de las importaciones en realidad se ejecutará después de que se evalúen las importaciones.

Sin embargo, puede ser útil invocar algunos efectos secundarios como simular fechas antes de importar un módulo.

Para evitar esta limitación, puedes reescribir las importaciones estáticas en dinámicas de esta manera:

diff
callFunctionWithSideEffect()
- import { value } from './some/module.js'
+ const { value } = await import('./some/module.js')

Al ejecutar vitest, puedes hacer esto automáticamente usando el método vi.hoisted.

diff
- callFunctionWithSideEffect()
import { value } from './some/module.js'
+ vi.hoisted(() => callFunctionWithSideEffect())

Este método devuelve el valor que fue devuelto por la factory. Puedes usar ese valor en tus factories vi.mock si necesitas un acceso fácil a variables definidas localmente:

ts
import { expect, vi } from 'vitest';
import { originalMethod } from './path/to/module.js';

const { mockedMethod } = vi.hoisted(() => {
  return { mockedMethod: vi.fn() };
});

vi.mock('./path/to/module.js', () => {
  return { originalMethod: mockedMethod };
});

mockedMethod.mockReturnValue(100);
expect(originalMethod()).toBe(100);

Ten en cuenta que este método también se puede llamar de forma asíncrona, incluso si tu entorno no admite top-level await:

ts
const promised = await vi.hoisted(async () => {
  const response = await fetch('https://jsonplaceholder.typicode.com/posts');
  return response.json();
});

vi.setConfig ​

  • Tipo: RuntimeConfig

Actualiza la configuración para el archivo de prueba actual. Este método solo admite opciones de configuración que afectarán al archivo de prueba actual:

ts
vi.setConfig({
  allowOnly: true,
  testTimeout: 10_000,
  hookTimeout: 10_000,
  clearMocks: true,
  restoreMocks: true,
  fakeTimers: {
    now: new Date(2021, 11, 19),
    // admite todo el objeto
  },
  maxConcurrency: 10,
  sequence: {
    hooks: 'stack',
    // solo admite "sequence.hooks"
  },
});

vi.resetConfig ​

  • Tipo: RuntimeConfig

Si se llamó a vi.setConfig antes, esto restablecerá la configuración al estado original.

Pager
AnteriorFunciones Mock
Siguienteexpect

Publicado bajo la licencia MIT.

Copyright (c) 2024 Mithril Contributors

https://v2.vitest.dev/api/vi

Publicado bajo la licencia MIT.

Copyright (c) 2024 Mithril Contributors