Skip to content
Vitest 3
Main Navigation Guía & APIConfiguraciónModo NavegadorAPI avanzada
3.2.0
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

Introducción

Por qué Vitest

Primeros pasos

Características

Configuración de Vitest

API

Referencia de la API de prueba

Funciones de Simulación

Vi

expect

expectTypeOf

assert

assertType

Guía

Interfaz de línea de comandos

Filtrado de Tests

Proyectos de prueba

Reportes

Cobertura

Instantáneas

Simulación (Mocking)

Paralelismo

Pruebas de Tipado

Interfaz de usuario de Vitest

Pruebas en el código fuente

Contexto de prueba

Anotaciones de prueba

Entorno de pruebas

Extender Matchers

Integraciones con IDE

Depuración

Errores comunes

Guía de migración

Migración a Vitest 3.0

Migración desde Jest

Rendimiento

Perfilado del rendimiento de las pruebas

Mejorando el Rendimiento

Modo Navegador

API Avanzadas

Comparaciones con otros ejecutores de pruebas

En esta página

Simulación (Mocking) ​

Al escribir pruebas, es común necesitar una versión "falsa" de un servicio interno o externo. Esto se conoce como simulación o mocking. Vitest facilita esta tarea a través de su utilidad vi, que puedes importar desde vitest o acceder globalmente si la configuración global está habilitada.

WARNING

¡Recuerda siempre limpiar o restaurar los mocks antes o después de cada ejecución de prueba para evitar que los cambios de estado del mock afecten a otras pruebas! Consulta la documentación de mockReset para más detalles.

Si no estás familiarizado con los métodos vi.fn, vi.mock o vi.spyOn, te recomendamos consultar primero la sección de la API.

Fechas ​

En ocasiones, es necesario controlar la fecha para asegurar la consistencia en las pruebas. Vitest utiliza el paquete @sinonjs/fake-timers para manipular temporizadores y la fecha del sistema. Puedes encontrar más detalles sobre la API específica aquí.

Ejemplo ​

js
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';

const businessHours = [9, 17];

function purchase() {
  const currentHour = new Date().getHours();
  const [open, close] = businessHours;

  if (currentHour > open && currentHour < close) {
    return { message: 'Success' };
  }

  return { message: 'Error' };
}

describe('purchasing flow', () => {
  beforeEach(() => {
    // Indica a Vitest que usaremos tiempo simulado
    vi.useFakeTimers();
  });

  afterEach(() => {
    // Restaura la fecha real después de cada ejecución de prueba
    vi.useRealTimers();
  });

  it('permite compras dentro del horario comercial', () => {
    // Establece la hora dentro del horario comercial
    const date = new Date(2000, 1, 1, 13);
    vi.setSystemTime(date);

    // Acceder a Date.now() devolverá la fecha establecida
    expect(purchase()).toEqual({ message: 'Success' });
  });

  it('no permite compras fuera del horario comercial', () => {
    // Establece la hora fuera del horario comercial
    const date = new Date(2000, 1, 1, 19);
    vi.setSystemTime(date);

    // Acceder a Date.now() devolverá la fecha establecida
    expect(purchase()).toEqual({ message: 'Error' });
  });
});

Funciones ​

La simulación de funciones se clasifica en dos categorías: espionaje y simulación.

A veces, solo necesitas verificar si una función específica fue llamada (y, opcionalmente, con qué argumentos). En estos casos, un "spy" (función espía) es suficiente, y puedes usarlo directamente con vi.spyOn() (más información aquí).

Sin embargo, los "spies" solo permiten espiar funciones; no pueden modificar su implementación. Si necesitas crear una versión falsa (o simulada) de una función, puedes usar vi.fn() (más información aquí).

Utilizamos Tinyspy como base para simular funciones, pero con una envoltura propia para compatibilidad con jest. Tanto vi.fn() como vi.spyOn() comparten los mismos métodos; sin embargo, solo el resultado de vi.fn() es invocable.

Ejemplo ​

js
import { afterEach, describe, expect, it, vi } from 'vitest';

const messages = {
  items: [
    { message: 'Simple test message', from: 'Testman' },
    // ...
  ],
  getLatest, // También puede ser un `getter` o `setter` si es compatible
};

function getLatest(index = messages.items.length - 1) {
  return messages.items[index];
}

describe('reading messages', () => {
  afterEach(() => {
    vi.restoreAllMocks();
  });

  it('debería obtener el último mensaje con un spy', () => {
    const spy = vi.spyOn(messages, 'getLatest');
    expect(spy.getMockName()).toEqual('getLatest');

    expect(messages.getLatest()).toEqual(
      messages.items[messages.items.length - 1]
    );

    expect(spy).toHaveBeenCalledTimes(1);

    spy.mockImplementationOnce(() => 'access-restricted');
    expect(messages.getLatest()).toEqual('access-restricted');

    expect(spy).toHaveBeenCalledTimes(2);
  });

  it('debería obtener con un mock', () => {
    const mock = vi.fn().mockImplementation(getLatest);

    expect(mock()).toEqual(messages.items[messages.items.length - 1]);
    expect(mock).toHaveBeenCalledTimes(1);

    mock.mockImplementationOnce(() => 'access-restricted');
    expect(mock()).toEqual('access-restricted');

    expect(mock).toHaveBeenCalledTimes(2);

    expect(mock()).toEqual(messages.items[messages.items.length - 1]);
    expect(mock).toHaveBeenCalledTimes(3);
  });
});

Más ​

  • Funciones Mock de Jest

Globales ​

Puedes simular variables globales que no están presentes con jsdom o node utilizando la utilidad vi.stubGlobal. Esto asignará el valor de la variable global a un objeto globalThis.

ts
import { vi } from 'vitest';

const IntersectionObserverMock = vi.fn(() => ({
  disconnect: vi.fn(),
  observe: vi.fn(),
  takeRecords: vi.fn(),
  unobserve: vi.fn(),
}));

vi.stubGlobal('IntersectionObserver', IntersectionObserverMock);

// Ahora puedes acceder a ella como `IntersectionObserver` o `window.IntersectionObserver`

Módulos ​

Los módulos simulados permiten interactuar con bibliotecas de terceros invocadas en otro código, lo que te permite probar argumentos, salidas o incluso redeclarar su implementación.

Consulta la sección de la API vi.mock() para una descripción más detallada de la API.

Algoritmo de Automocking ​

Si tu código importa un módulo simulado sin un archivo __mocks__ asociado o una factory para este, Vitest simulará el módulo invocándolo y falsificando cada exportación.

Se aplican los siguientes principios:

  • Todos los arrays se vaciarán.
  • Todos los primitivos y colecciones permanecerán inalterados.
  • Todos los objetos se clonarán profundamente.
  • Todas las instancias de clases y sus prototipos se clonarán profundamente.

Módulos Virtuales ​

Vitest soporta la simulación de módulos virtuales de Vite. Funciona de manera diferente a cómo se tratan los módulos virtuales en Jest. En lugar de pasar virtual: true a una función vi.mock, necesitas informar a Vite que el módulo existe, de lo contrario fallará durante el análisis. Puedes hacerlo de varias maneras:

  1. Proporcionar un alias
ts
import { defineConfig } from 'vitest/config';
import { resolve } from 'node:path';
export default defineConfig({
  test: {
    alias: {
      '$app/forms': resolve('./mocks/forms.js'),
    },
  },
});
  1. Proporcionar un plugin que resuelva un módulo virtual
ts
import { defineConfig } from 'vitest/config';
export default defineConfig({
  plugins: [
    {
      name: 'virtual-modules',
      resolveId(id) {
        if (id === '$app/forms') {
          return 'virtual:$app/forms';
        }
      },
    },
  ],
});

El beneficio del segundo enfoque es que puedes crear dinámicamente diferentes puntos de entrada virtuales. Si rediriges varios módulos virtuales a un solo archivo, todos se verán afectados por vi.mock, así que asegúrate de usar identificadores únicos.

Trampas de Mocking ​

Ten en cuenta que no es posible simular llamadas a métodos que se invocan dentro de otros métodos del mismo archivo. Por ejemplo, en este código:

ts
export function foo() {
  return 'foo';
}

export function foobar() {
  return `${foo()}bar`;
}

No es posible simular el método foo desde el exterior porque se referencia directamente. Por lo tanto, este código no tendrá ningún efecto en la llamada a foo dentro de foobar (pero sí afectará la llamada a foo en otros módulos):

ts
import { vi } from 'vitest';
import * as mod from './foobar.js';

// Esto solo afectará a "foo" fuera del módulo original
vi.spyOn(mod, 'foo');
vi.mock('./foobar.js', async importOriginal => {
  return {
    ...(await importOriginal<typeof import('./foobar.js')>()),
    // Esto solo afectará a "foo" fuera del módulo original
    foo: () => 'mocked',
  };
});

Puedes confirmar este comportamiento implementando el método foobar directamente:

ts
import * as mod from './foobar.js';

vi.spyOn(mod, 'foo');

// foo exportado referencia al método simulado
mod.foobar(mod.foo);
ts
export function foo() {
  return 'foo';
}

export function foobar(injectedFoo) {
  return injectedFoo === foo; // false
}

Este es el comportamiento esperado. Generalmente, es una señal de mal diseño de código cuando la simulación se utiliza de esta manera. Considera refactorizar tu código en múltiples archivos o mejorar la arquitectura de tu aplicación utilizando técnicas como la inyección de dependencias.

Ejemplo ​

js
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
import { Client } from 'pg';
import { failure, success } from './handlers.js';

// Obtener tareas
export async function getTodos(event, context) {
  const client = new Client({
    // ...clientOptions
  });

  await client.connect();

  try {
    const result = await client.query('SELECT * FROM todos;');

    client.end();

    return success({
      message: `${result.rowCount} item(s) returned`,
      data: result.rows,
      status: true,
    });
  } catch (e) {
    console.error(e.stack);

    client.end();

    return failure({ message: e, status: false });
  }
}

vi.mock('pg', () => {
  const Client = vi.fn();
  Client.prototype.connect = vi.fn();
  Client.prototype.query = vi.fn();
  Client.prototype.end = vi.fn();

  return { Client };
});

vi.mock('./handlers.js', () => {
  return {
    success: vi.fn(),
    failure: vi.fn(),
  };
});

describe('get a list of todo items', () => {
  let client;

  beforeEach(() => {
    client = new Client();
  });

  afterEach(() => {
    vi.clearAllMocks();
  });

  it('debería devolver los elementos correctamente', async () => {
    client.query.mockResolvedValueOnce({ rows: [], rowCount: 0 });

    await getTodos();

    expect(client.connect).toBeCalledTimes(1);
    expect(client.query).toBeCalledWith('SELECT * FROM todos;');
    expect(client.end).toBeCalledTimes(1);

    expect(success).toBeCalledWith({
      message: '0 item(s) returned',
      data: [],
      status: true,
    });
  });

  it('debería lanzar un error', async () => {
    const mError = new Error('Unable to retrieve rows');
    client.query.mockRejectedValueOnce(mError);

    await getTodos();

    expect(client.connect).toBeCalledTimes(1);
    expect(client.query).toBeCalledWith('SELECT * FROM todos;');
    expect(client.end).toBeCalledTimes(1);
    expect(failure).toBeCalledWith({ message: mError, status: false });
  });
});

Sistema de Archivos ​

La simulación del sistema de archivos garantiza que las pruebas no dependan del sistema de archivos real, haciéndolas más fiables y predecibles. Este aislamiento ayuda a evitar efectos secundarios de pruebas previas. Permite probar condiciones de error y casos límite que serían difíciles o imposibles de replicar con un sistema de archivos real, como problemas de permisos, escenarios de disco lleno o errores de lectura/escritura.

Vitest no proporciona ninguna API de simulación de sistema de archivos de serie. Puedes usar vi.mock para simular el módulo fs manualmente, pero su mantenimiento es complejo. En su lugar, recomendamos usar memfs para esta tarea. memfs crea un sistema de archivos en memoria, que simula operaciones del sistema de archivos sin tocar el disco real. Este enfoque es rápido y seguro, evitando efectos secundarios en el sistema de archivos real.

Ejemplo ​

Para redirigir automáticamente cada llamada a fs a memfs, puedes crear los archivos __mocks__/fs.cjs y __mocks__/fs/promises.cjs en la raíz de tu proyecto:

ts
// También podemos usar `import`, pero entonces
// cada exportación debe ser definida explícitamente

const { fs } = require('memfs');
module.exports = fs;
ts
// También podemos usar `import`, pero entonces
// cada exportación debe ser definida explícitamente

const { fs } = require('memfs');
module.exports = fs.promises;
ts
import { readFileSync } from 'node:fs';

export function readHelloWorld(path) {
  return readFileSync(path, 'utf-8');
}
ts
import { beforeEach, expect, it, vi } from 'vitest';
import { fs, vol } from 'memfs';
import { readHelloWorld } from './read-hello-world.js';

// Indica a Vitest que use el mock de fs de la carpeta __mocks__
// Esto se puede hacer en un archivo de configuración si fs siempre debe ser simulado
vi.mock('node:fs');
vi.mock('node:fs/promises');

beforeEach(() => {
  // Restablece el estado del sistema de archivos en memoria
  vol.reset();
});

it('debería devolver el texto correcto', () => {
  const path = '/hello-world.txt';
  fs.writeFileSync(path, 'hello world');

  const text = readHelloWorld(path);
  expect(text).toBe('hello world');
});

it('puede devolver un valor varias veces', () => {
  // Puedes usar vol.fromJSON para definir varios archivos
  vol.fromJSON(
    {
      './dir1/hw.txt': 'hello dir1',
      './dir2/hw.txt': 'hello dir2',
    },
    // Directorio de trabajo actual por defecto
    '/tmp'
  );

  expect(readHelloWorld('/tmp/dir1/hw.txt')).toBe('hello dir1');
  expect(readHelloWorld('/tmp/dir2/hw.txt')).toBe('hello dir2');
});

Solicitudes ​

Dado que Vitest se ejecuta en Node.js, simular solicitudes de red es complejo; las API web no están disponibles, por lo que necesitamos algo que imite el comportamiento de la red. Recomendamos Mock Service Worker para lograr esto. Permite simular solicitudes de red http, WebSocket y GraphQL, y es independiente del framework.

Mock Service Worker (MSW) funciona interceptando las solicitudes que tus pruebas realizan, lo que te permite usarlo sin cambiar el código de tu aplicación. En el navegador, esto utiliza la API de Service Worker. En Node.js, y para Vitest, utiliza la biblioteca @mswjs/interceptors. Para obtener más información sobre MSW, lee su introducción

Configuración ​

Puedes usarlo de la siguiente manera en tu archivo de configuración

js
import { afterAll, afterEach, beforeAll } from 'vitest';
import { setupServer } from 'msw/node';
import { http, HttpResponse } from 'msw';

const posts = [
  {
    userId: 1,
    id: 1,
    title: 'first post title',
    body: 'first post body',
  },
  // ...
];

export const restHandlers = [
  http.get('https://rest-endpoint.example/path/to/posts', () => {
    return HttpResponse.json(posts);
  }),
];

const server = setupServer(...restHandlers);

// Iniciar el servidor antes de todas las pruebas
beforeAll(() => server.listen({ onUnhandledRequest: 'error' }));

// Cerrar el servidor después de todas las pruebas
afterAll(() => server.close());

// Restablecer los manejadores después de cada prueba para el aislamiento de la prueba
afterEach(() => server.resetHandlers());
js
import { afterAll, afterEach, beforeAll } from 'vitest';
import { setupServer } from 'msw/node';
import { graphql, HttpResponse } from 'msw';

const posts = [
  {
    userId: 1,
    id: 1,
    title: 'first post title',
    body: 'first post body',
  },
  // ...
];

const graphqlHandlers = [
  graphql.query('ListPosts', () => {
    return HttpResponse.json({
      data: { posts },
    });
  }),
];

const server = setupServer(...graphqlHandlers);

// Iniciar el servidor antes de todas las pruebas
beforeAll(() => server.listen({ onUnhandledRequest: 'error' }));

// Cerrar el servidor después de todas las pruebas
afterAll(() => server.close());

// Restablecer los manejadores después de cada prueba para el aislamiento de la prueba
afterEach(() => server.resetHandlers());
js
import { afterAll, afterEach, beforeAll } from 'vitest';
import { setupServer } from 'msw/node';
import { ws } from 'msw';

const chat = ws.link('wss://chat.example.com');

const wsHandlers = [
  chat.addEventListener('connection', ({ client }) => {
    client.addEventListener('message', event => {
      console.log('Received message from client:', event.data);
      // Reenviar el mensaje recibido al cliente
      client.send(`Server received: ${event.data}`);
    });
  }),
];

const server = setupServer(...wsHandlers);

// Iniciar el servidor antes de todas las pruebas
beforeAll(() => server.listen({ onUnhandledRequest: 'error' }));

// Cerrar el servidor después de todas las pruebas
afterAll(() => server.close());

// Restablecer los manejadores después de cada prueba para el aislamiento de la prueba
afterEach(() => server.resetHandlers());

Configurar el servidor con onUnhandledRequest: 'error' garantiza que se lance un error cada vez que haya una solicitud que no tenga un controlador de solicitudes correspondiente.

Más ​

MSW ofrece muchas más funcionalidades. Puedes acceder a cookies y parámetros de consulta, definir respuestas de error simuladas, ¡y mucho más! Para ver todo lo que puedes hacer con MSW, lee su documentación.

Temporizadores ​

Cuando probamos código que involucra tiempos de espera o intervalos, en lugar de hacer que nuestras pruebas esperen o caduquen, podemos acelerar nuestras pruebas usando temporizadores "falsos" que simulan llamadas a setTimeout y setInterval.

Consulta la sección de la API vi.useFakeTimers para una descripción más detallada de la API.

Ejemplo ​

js
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';

function executeAfterTwoHours(func) {
  setTimeout(func, 1000 * 60 * 60 * 2); // 2 horas
}

function executeEveryMinute(func) {
  setInterval(func, 1000 * 60); // 1 minuto
}

const mock = vi.fn(() => console.log('executed'));

describe('delayed execution', () => {
  beforeEach(() => {
    vi.useFakeTimers();
  });
  afterEach(() => {
    vi.restoreAllMocks();
  });
  it('debería ejecutar la función', () => {
    executeAfterTwoHours(mock);
    vi.runAllTimers();
    expect(mock).toHaveBeenCalledTimes(1);
  });
  it('no debería ejecutar la función', () => {
    executeAfterTwoHours(mock);
    // Avanzar 2ms no activará la función
    vi.advanceTimersByTime(2);
    expect(mock).not.toHaveBeenCalled();
  });
  it('debería ejecutarse cada minuto', () => {
    executeEveryMinute(mock);
    vi.advanceTimersToNextTimer();
    expect(mock).toHaveBeenCalledTimes(1);
    vi.advanceTimersToNextTimer();
    expect(mock).toHaveBeenCalledTimes(2);
  });
});

Clases ​

Puedes simular una clase completa con una sola llamada a vi.fn; dado que todas las clases también son funciones, esto funciona por defecto. Ten en cuenta que actualmente Vitest no respeta la palabra clave new, por lo que new.target siempre es undefined dentro del cuerpo de una función.

ts
class Dog {
  name: string;

  constructor(name: string) {
    this.name = name;
  }

  static getType(): string {
    return 'animal';
  }

  greet = (): string => {
    return `Hi! My name is ${this.name}!`;
  };

  speak(): string {
    return 'bark!';
  }

  isHungry() {}
  feed() {}
}

Podemos recrear esta clase con funciones ES5:

ts
const Dog = vi.fn(function (name) {
  this.name = name;
  // Simular métodos de instancia en el constructor; cada instancia tendrá su propio spy
  this.greet = vi.fn(() => `Hi! My name is ${this.name}!`);
});

// Observa que los métodos estáticos se simulan directamente en la función,
// no en la instancia de la clase
Dog.getType = vi.fn(() => 'mocked animal');

// Simular los métodos "speak" y "feed" en cada instancia de una clase
// Todas las instancias de `new Dog()` heredarán y compartirán estos spies
Dog.prototype.speak = vi.fn(() => 'loud bark!');
Dog.prototype.feed = vi.fn();

WARNING

Si una función constructora devuelve un valor no primitivo, ese valor se convertirá en el resultado de la expresión new. En este caso, el [[Prototype]] podría no vincularse correctamente:

ts
const CorrectDogClass = vi.fn(function (name) {
  this.name = name;
});

const IncorrectDogClass = vi.fn(name => ({
  name,
}));

const Marti = new CorrectDogClass('Marti');
const Newt = new IncorrectDogClass('Newt');

Marti instanceof CorrectDogClass; // ✅ true
Newt instanceof IncorrectDogClass; // ❌ false!

¿CUÁNDO USAR?

Por lo general, recrearías una clase como esta dentro de la fábrica de módulos si la clase se reexporta desde otro módulo:

ts
import { Dog } from './dog.js';

vi.mock(import('./dog.js'), () => {
  const Dog = vi.fn();
  Dog.prototype.feed = vi.fn();
  // ... otros mocks
  return { Dog };
});

Este método también puede utilizarse para pasar una instancia de una clase a una función que acepta la misma interfaz:

ts
function feed(dog: Dog) {
  // ...
}
ts
import { expect, test, vi } from 'vitest';
import { feed } from '../src/feed.js';

const Dog = vi.fn();
Dog.prototype.feed = vi.fn();

test('puede alimentar perros', () => {
  const dogMax = new Dog('Max');

  feed(dogMax);

  expect(dogMax.feed).toHaveBeenCalled();
  expect(dogMax.isHungry()).toBe(false);
});

Ahora, cuando creamos una nueva instancia de la clase Dog, su método speak (junto con feed y greet) ya está simulado:

ts
const Cooper = new Dog('Cooper');
Cooper.speak(); // loud bark!
Cooper.greet(); // Hi! My name is Cooper!

// Puedes usar las aserciones incluidas para verificar la validez de la llamada
expect(Cooper.speak).toHaveBeenCalled();
expect(Cooper.greet).toHaveBeenCalled();

const Max = new Dog('Max');

// Los métodos asignados al prototipo se comparten entre instancias
expect(Max.speak).toHaveBeenCalled();
expect(Max.greet).not.toHaveBeenCalled();

Podemos reasignar el valor de retorno para una instancia específica:

ts
const dog = new Dog('Cooper');

// "vi.mocked" es un asistente de tipo, ya que
// TypeScript no sabe que Dog es una clase simulada,
// envuelve cualquier función en un tipo MockInstance<T>
// sin validar si la función es un mock
vi.mocked(dog.speak).mockReturnValue('woof woof');

dog.speak(); // woof woof

Para simular la propiedad, podemos usar el método vi.spyOn(dog, 'name', 'get'). Esto permite usar aserciones con el spy en la propiedad simulada:

ts
const dog = new Dog('Cooper');

const nameSpy = vi.spyOn(dog, 'name', 'get').mockReturnValue('Max');

expect(dog.name).toBe('Max');
expect(nameSpy).toHaveBeenCalledTimes(1);

TIP

También puedes espiar getters y setters usando el mismo método.

Guía rápida ​

INFO

vi en los ejemplos siguientes se importa directamente de vitest. También puedes usarlo globalmente, si estableces globals en true en tu configuración.

Quiero…

Simular variables exportadas ​

js
export const getter = 'variable';
ts
import * as exports from './example.js';

vi.spyOn(exports, 'getter', 'get').mockReturnValue('mocked');

Simular una función exportada ​

  1. Ejemplo con vi.mock:

WARNING

No olvides que una llamada a vi.mock se procesa al principio del archivo. Siempre se ejecutará antes de cualquier importación.

ts
export function method() {}
ts
import { method } from './example.js';

vi.mock('./example.js', () => ({
  method: vi.fn(),
}));
  1. Ejemplo con vi.spyOn:
ts
import * as exports from './example.js';

vi.spyOn(exports, 'method').mockImplementation(() => {});

Simular la implementación de una clase exportada ​

  1. Ejemplo con vi.mock y .prototype:
ts
export class SomeClass {}
ts
import { SomeClass } from './example.js';

vi.mock(import('./example.js'), () => {
  const SomeClass = vi.fn();
  SomeClass.prototype.someMethod = vi.fn();
  return { SomeClass };
});
// Las instancias de SomeClass.mock tendrán SomeClass
  1. Ejemplo con vi.spyOn:
ts
import * as mod from './example.js';

const SomeClass = vi.fn();
SomeClass.prototype.someMethod = vi.fn();

vi.spyOn(mod, 'SomeClass').mockImplementation(SomeClass);

Espiar un objeto devuelto por una función ​

  1. Ejemplo usando caché:
ts
export function useObject() {
  return { method: () => true };
}
ts
import { useObject } from './example.js';

const obj = useObject();
obj.method();
ts
import { useObject } from './example.js';

vi.mock(import('./example.js'), () => {
  let _cache;
  const useObject = () => {
    if (!_cache) {
      _cache = {
        method: vi.fn(),
      };
    }
    // Ahora, cada vez que se llame a useObject(), devolverá
    // la misma referencia de objeto
    return _cache;
  };
  return { useObject };
});

const obj = useObject();
// obj.method fue llamado dentro de alguna-ruta
expect(obj.method).toHaveBeenCalled();

Simular parte de un módulo ​

ts
import { mocked, original } from './some-path.js';

vi.mock(import('./some-path.js'), async importOriginal => {
  const mod = await importOriginal();
  return {
    ...mod,
    mocked: vi.fn(),
  };
});
original(); // Tiene comportamiento original
mocked(); // Es una función spy

WARNING

No olvides que esto solo afecta el acceso externo. En este ejemplo, si original llama a mocked internamente, siempre llamará a la función definida en el módulo, no en la fábrica de mocks.

Simular la fecha actual ​

Para simular la hora de Date, puedes usar la función auxiliar vi.setSystemTime. Este valor no se restablecerá automáticamente entre pruebas.

Ten en cuenta que usar vi.useFakeTimers también cambia la hora de Date.

ts
const mockDate = new Date(2022, 0, 1);
vi.setSystemTime(mockDate);
const now = new Date();
expect(now.valueOf()).toBe(mockDate.valueOf());
// Restablecer tiempo simulado
vi.useRealTimers();

Simular una variable global ​

Puedes establecer una variable global asignando un valor a globalThis o usando la utilidad vi.stubGlobal. Al usar vi.stubGlobal, no se restablecerá automáticamente entre pruebas, a menos que habilites la opción de configuración unstubGlobals o llames a vi.unstubAllGlobals.

ts
vi.stubGlobal('__VERSION__', '1.0.0');
expect(__VERSION__).toBe('1.0.0');

Simular import.meta.env ​

  1. Para cambiar una variable de entorno, basta con asignarle un nuevo valor.

WARNING

El valor de la variable de entorno no se restablecerá automáticamente entre pruebas.

ts
import { beforeEach, expect, it } from 'vitest';

// Puedes restablecerlo manualmente en el gancho beforeEach
const originalViteEnv = import.meta.env.VITE_ENV;

beforeEach(() => {
  import.meta.env.VITE_ENV = originalViteEnv;
});

it('cambia el valor', () => {
  import.meta.env.VITE_ENV = 'staging';
  expect(import.meta.env.VITE_ENV).toBe('staging');
});
  1. Si deseas restablecer automáticamente los valores, puedes usar la utilidad vi.stubEnv con la opción de configuración unstubEnvs habilitada (o llamar a vi.unstubAllEnvs manualmente en un gancho beforeEach):
ts
import { expect, it, vi } from 'vitest';

// Antes de ejecutar las pruebas "VITE_ENV" es "test"
import.meta.env.VITE_ENV === 'test';

it('cambia el valor', () => {
  vi.stubEnv('VITE_ENV', 'staging');
  expect(import.meta.env.VITE_ENV).toBe('staging');
});

it('el valor se restaura antes de ejecutar otra prueba', () => {
  expect(import.meta.env.VITE_ENV).toBe('test');
});
ts
export default defineConfig({
  test: {
    unstubEnvs: true,
  },
});
Pager
AnteriorInstantáneas
SiguienteParalelismo

Publicado bajo la licencia MIT.

Copyright (c) 2021-Present Vitest Team

https://vitest.dev/guide/mocking

Publicado bajo la licencia MIT.

Copyright (c) 2021-Present Vitest Team