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
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
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
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
.
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:
- Proporcionar un alias
import { defineConfig } from 'vitest/config';
import { resolve } from 'node:path';
export default defineConfig({
test: {
alias: {
'$app/forms': resolve('./mocks/forms.js'),
},
},
});
- Proporcionar un plugin que resuelva un módulo virtual
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:
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):
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:
import * as mod from './foobar.js';
vi.spyOn(mod, 'foo');
// foo exportado referencia al método simulado
mod.foobar(mod.foo);
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
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:
// También podemos usar `import`, pero entonces
// cada exportación debe ser definida explícitamente
const { fs } = require('memfs');
module.exports = fs;
// También podemos usar `import`, pero entonces
// cada exportación debe ser definida explícitamente
const { fs } = require('memfs');
module.exports = fs.promises;
import { readFileSync } from 'node:fs';
export function readHelloWorld(path) {
return readFileSync(path, 'utf-8');
}
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
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());
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());
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
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.
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:
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:
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:
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:
function feed(dog: Dog) {
// ...
}
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:
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:
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:
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
export const getter = 'variable';
import * as exports from './example.js';
vi.spyOn(exports, 'getter', 'get').mockReturnValue('mocked');
Simular una función exportada
- 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.
export function method() {}
import { method } from './example.js';
vi.mock('./example.js', () => ({
method: vi.fn(),
}));
- Ejemplo con
vi.spyOn
:
import * as exports from './example.js';
vi.spyOn(exports, 'method').mockImplementation(() => {});
Simular la implementación de una clase exportada
- Ejemplo con
vi.mock
y.prototype
:
export class SomeClass {}
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
- Ejemplo con
vi.spyOn
:
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
- Ejemplo usando caché:
export function useObject() {
return { method: () => true };
}
import { useObject } from './example.js';
const obj = useObject();
obj.method();
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
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
.
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
.
vi.stubGlobal('__VERSION__', '1.0.0');
expect(__VERSION__).toBe('1.0.0');
Simular import.meta.env
- 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.
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');
});
- Si deseas restablecer automáticamente los valores, puedes usar la utilidad
vi.stubEnv
con la opción de configuraciónunstubEnvs
habilitada (o llamar avi.unstubAllEnvs
manualmente en un ganchobeforeEach
):
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');
});
export default defineConfig({
test: {
unstubEnvs: true,
},
});